Skip to content

Instantly share code, notes, and snippets.

@maxgherman
Last active August 29, 2015 14:03
Show Gist options
  • Save maxgherman/04662d0f263c0f9390ab to your computer and use it in GitHub Desktop.
Save maxgherman/04662d0f263c0f9390ab to your computer and use it in GitHub Desktop.
Haskell / Scala Infinite Streams in C#
using System;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApplication
{
class Program
{
static void Main(string[] args)
{
Stream<int> s = null;
// stream of zeroes
s = new Stream<int>(0, () => s);
Print(s);
// stream of 0 1
s = 0 * new Stream<int>(1, () => s);
Print(s);
// 0 1
s = 0 * new Stream<int>(1);
Print(s);
// 0 1 Empty
s = 0 * (1 * Stream<int>.Empty);
Print(s);
// memoizaion
s = new Stream<int>(() => 0, n =>
{
Console.Write("Eval : {0} ", n);
return n + 1;
});
Print(s);
Print(s);
// fibonacci sequence with tuples
var s1 = (new Tuple<int, int>(0, 0) * new Stream<Tuple<int, int>>(() => new Tuple<int, int>(1, 0),
pair => new Tuple<int, int>(pair.Item1 + pair.Item2, pair.Item1))).Select(item => item.Head.Value.Item1);
Print(s1);
// fibonacci sequence with dynamic
s1 = ((new { Item1 = 0, Item2 = 0 }) * new Stream<dynamic>(() => new { Item1 = 1, Item2 = 0 },
pair => new { Item1 = pair.Item1 + pair.Item2, Item2 = pair.Item1 })).Select(item => (int)item.Head.Value.Item1);
Print(s1);
// fibonacci sequence with Func
Func<int, int, Stream<int>> fibonacci = null;
fibonacci = (h, n) => new Stream<int>(() => h, () => fibonacci(n, h + n));
s = 0 * fibonacci(1, 1);
Print(s);
// fibonacci sequence with Zip
s = 0 * new Stream<int>(1);
Func<Stream<int>, Stream<int>> fibonacci2 = null;
fibonacci2 = stream =>
{
var filtered = stream.Zip(stream.Tail, (n1, n2) => new Stream<int>(() => n1.Head.Value + n2.Head.Value, (Func<Stream<int>>)null)).First();
return new Stream<int>(stream.Head, () => fibonacci2(stream.Tail.Head * filtered));
};
Print(fibonacci2(s));
// odd numbers enumarable
s = new Stream<int>(() => 1, n => n + 1);
Print(s.Where(st => st.Head.Value % 2 != 0).Select(item => item.Head.Value));
// odd numbers stream
s = new Stream<int>(() => 1, n => n + 2);
Print(s);
// odd numbers filtered stream
s = new Stream<int>(() => 1, n => n + 1);
Func<Stream<int>, Stream<int>> filterOdd = null;
filterOdd = stream =>
{
var filtered = stream.Tail.Where(item => item.Head.Value % 2 != 0);
return new Stream<int>(stream.Head, () => filterOdd(new Stream<int>(filtered)));
};
Print(filterOdd(s));
// square root of 2 ( Newton's method )
var sQ = new Stream<double>(() => 1, x => 0.5 * x + 1 / x);
Print(sQ);
// unfaithful Eratosthenes sieve
s = new Stream<int>(() => 3, n => n + 2);
Func<Stream<int>, Stream<int>> sieve = null;
sieve = stream =>
{
var filtered = stream.Tail.Where(item => item.Head.Value % stream.Head.Value != 0);
return new Stream<int>(stream.Head, () => sieve(new Stream<int>(filtered)));
};
Print(2 * sieve(s));
// Power
Func<double, double, Stream<double>> fPow = null;
fPow = (x, m) => new Stream<double>(() => x, () => fPow(x * m, m));
Print(fPow(2, 2));
// archtan 0.2, James Gregory: x - x^3/3 + x^5/5 - x^7/7
s = new Stream<int>(() => 3, n => n + 2);
Func<double, int, Stream<int>, Stream<double>> fArchtan = null;
fArchtan = (x, sign, stream) =>
{
Func<double> fValue = () => x + sign * fPow(x, x).Skip(stream.Head.Value - 1).First().Head.Value / stream.Head.Value;
Func<Stream<double>> fNext = () => fArchtan(fValue(), -1*sign, stream.Tail);
return new Stream<double>(x, fNext);
};
Print(fArchtan(0.2, -1, s));
// PI, John Machin
var v1 = fArchtan(1 / 5.0, -1, s).Skip(20).First().Head.Value;
var v2 = fArchtan(1 / 239.0, -1, s).Skip(20).First().Head.Value;
Console.WriteLine(4 * (4 * v1 - v2));
Console.ReadKey();
}
private static void Print<T>(Stream<T> stream, int? count = 20)
{
stream.Take(count.Value).ToList().ForEach(item => Console.Write("{0} ", item.Head.Value));
Console.WriteLine();
Console.WriteLine();
}
private static void Print<T>(IEnumerable<T> stream, int? count = 20)
{
stream.Take(count.Value).ToList().ForEach(item => Console.Write("{0} ", item));
Console.WriteLine();
Console.WriteLine();
}
}
public class Stream<T> : IEnumerable<Stream<T>>
{
private Lazy<T> lazyValue;
private Lazy<Stream<T>> _tail;
public virtual Lazy<T> Head { get { return lazyValue; } }
public virtual bool IsEmpty { get { return false; } }
public virtual Stream<T> Tail
{
get
{
return _tail == null ? (Stream<T>)null : _tail.Value;
}
}
private Stream() { }
public Stream(Lazy<T> value, Func<Stream<T>> tail = null)
{
lazyValue = value;
_tail = tail == null ? null : new Lazy<Stream<T>>(tail);
}
public Stream(T value, Func<Stream<T>> tail = null)
: this(new Lazy<T>(() => value), tail)
{ }
public Stream(Func<T> value, Func<Stream<T>> tail = null)
: this(new Lazy<T>(value), tail)
{ }
public Stream(Func<T> value, Func<T, Stream<T>> tail = null)
: this(new Lazy<T>(value), null)
{
_tail = tail == null ? null : new Lazy<Stream<T>>(() => tail(Head.Value));
}
public Stream(Func<T> value, Func<T, T> evaluator = null)
: this(new Lazy<T>(value), null)
{
if (evaluator != null)
{
Func<Stream<T>> f = null;
f = () => new Stream<T>(() => evaluator(Head.Value), evaluator);
_tail = new Lazy<Stream<T>>(f);
}
}
public Stream(IEnumerable<Stream<T>> sequence)
{
lazyValue = new Lazy<T>(() => sequence.First().Head.Value);
_tail = new Lazy<Stream<T>>(() => new SequenceStream<T>(sequence.Skip(1)));
}
public static Stream<T> Empty { get { return new EmptyStream<T>(); } }
public static Stream<T> operator *(T value, Stream<T> stream)
{
if (stream.IsEmpty) return new Stream<T>(value, (Func<Stream<T>>)null);
return (() => value) * stream;
}
public static Stream<T> operator *(Lazy<T> value, Stream<T> stream)
{
if (stream.IsEmpty) return new Stream<T>(value, (Func<Stream<T>>)null);
return new Stream<T>(value, () => stream);
}
public static Stream<T> operator *(Func<T> value, Stream<T> stream)
{
if (stream.IsEmpty) return new Stream<T>(value, (Func<Stream<T>>)null);
return new Stream<T>(value, () => stream);
}
public virtual IEnumerator<Stream<T>> GetEnumerator()
{
var stream = this;
while (stream != null && !stream.IsEmpty)
{
yield return stream;
if (stream.Tail == null) yield break;
stream = stream.Tail;
}
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
class EmptyStream<T> : Stream<T>
{
public override Lazy<T> Head
{
get { throw new Exception("Empty stream"); }
}
public override Stream<T> Tail
{
get { throw new Exception("Empty stream"); }
}
public override IEnumerator<Stream<T>> GetEnumerator()
{
throw new Exception("Empty stream");
}
public override bool IsEmpty
{
get { return true; }
}
}
class SequenceStream<T> : Stream<T>
{
private readonly IEnumerable<Stream<T>> _sequence;
public override Lazy<T> Head
{
get { return _sequence.First().Head; }
}
public override Stream<T> Tail
{
get { return _sequence.Skip(1).First().Tail; }
}
public override IEnumerator<Stream<T>> GetEnumerator()
{
return _sequence.GetEnumerator();
}
public override bool IsEmpty
{
get { return !_sequence.Any(); }
}
public SequenceStream(IEnumerable<Stream<T>> sequence)
{
this._sequence = sequence;
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment