Created
November 6, 2012 15:42
-
-
Save hodzanassredin/4025522 to your computer and use it in GitHub Desktop.
iteratees in csharp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Text; | |
using System.Threading.Tasks; | |
//http://jazzy.id.au/default/2012/11/06/iteratees_for_imperative_programmers.html | |
namespace Iteratee | |
{ | |
class Program | |
{ | |
static void Main(string[] args) | |
{ | |
var source = List<String>.Cons(new[] { "3d", "2d", "head" }); | |
var dropTwo = drop<string>(1); | |
var result = dropTwo.Bind(peek<String>).Enumerate(source).Run(); | |
Console.WriteLine(result); | |
var sourceObj = List<Object>.Cons(new object[] { "3d", "2d", "head" }); | |
var resultM = (from dropTwoM in drop<object>(1) | |
from dropAndPeekM in peek<object>(dropTwoM) | |
select dropAndPeekM).Enumerate<Object, Maybe<Object>>(sourceObj).Run(); | |
Console.WriteLine(resultM); | |
Console.ReadKey(); | |
} | |
public static Iteratee<T, Maybe<T>> head<T>() | |
{ | |
Func<Input<T>, Iteratee<T, Maybe<T>>> step = null; | |
step = inputE => inputE.Match<Iteratee<T, Maybe<T>>, T>( | |
eof => new Done<T, Maybe<T>>(new Nothing<T>(), eof), | |
empty => new Cont<T, Maybe<T>>(step), | |
element => new Done<T, Maybe<T>>(new Just<T>(element.GetValue()), new InputEmpty<T>()) | |
); | |
return new Cont<T, Maybe<T>>(step); | |
} | |
public static Iteratee<T, Maybe<T>> peek<T>(Unit u) | |
{ | |
Func<Input<T>, Iteratee<T, Maybe<T>>> step = null; | |
step = inputE => inputE.Match<Iteratee<T, Maybe<T>>, T>( | |
eof => new Done<T, Maybe<T>>(new Nothing<T>(), eof), | |
empty => new Cont<T, Maybe<T>>(step), | |
element => new Done<T, Maybe<T>>(new Just<T>(element.GetValue()), element) | |
); | |
return new Cont<T, Maybe<T>>(step); | |
} | |
public static Iteratee<T, Unit> drop<T>(int n) | |
{ | |
if (n == 0) return new Done<T, Unit>(new Unit(), new InputEmpty<T>()); | |
Func<Input<T>, Iteratee<T, Unit>> step = null; | |
step = inputE => inputE.Match( | |
eof => new Done<T, Unit>(new Unit(), eof), | |
empty => new Cont<T, Unit>(step), | |
element => drop<T>(n - 1) | |
); | |
return new Cont<T, Unit>(step); | |
} | |
public static Iteratee<T, int> length<T>() | |
{ | |
Func<int, Input<T>, Iteratee<T, int>> step = null; | |
step = (acc, inputE) => inputE.Match<Iteratee<T, int>, T>( | |
eof => new Done<T, int>(acc, eof), | |
empty => new Cont<T, int>(input => step(acc, input)), | |
element => new Cont<T, int>(input => step(acc + 1, input)) | |
); | |
return new Cont<T, int>(input => step(0, input)); | |
} | |
} | |
public class Unit | |
{ | |
public Unit(Action a) | |
{ | |
a(); | |
} | |
public Unit() | |
{ | |
} | |
} | |
public class List<T> | |
{ | |
public static readonly List<T> Nil = new List<T>(); | |
public static List<T> Cons(T head, List<T> tail) { return new List<T>(head, tail); } | |
public static List<T> Cons(params T[] vals) | |
{ | |
return vals.Aggregate(Nil, (current, val) => Cons(val, current)); | |
} | |
private T _head; | |
protected bool _isNil = false; | |
public bool IsNil | |
{ | |
get | |
{ | |
return _isNil; | |
} | |
} | |
public T Head | |
{ | |
get | |
{ | |
if (IsNil) throw new ArgumentException(); | |
return _head; | |
} | |
private set { _head = value; } | |
} | |
private List<T> _tail; | |
public List<T> Tail | |
{ | |
get | |
{ | |
if (IsNil) throw new ArgumentException(); | |
return _tail; | |
} | |
private set { _tail = value; } | |
} | |
protected List() | |
{ | |
_isNil = true; | |
} | |
public List(T head, List<T> tail) | |
{ | |
if (tail == null) throw new ArgumentException(); | |
_head = head; | |
_tail = tail; | |
} | |
public override string ToString() | |
{ | |
return "[ " + ToStr() + " ]"; | |
} | |
public string ToStr() | |
{ | |
if (IsNil) return "Nil"; | |
else return (_head == null ? "Null" : _head.ToString()) + ":" + Tail.ToStr(); | |
} | |
public IEnumerable<T> ToEnumerable() | |
{ | |
var l = this; | |
while (true) | |
{ | |
if (l.IsNil) yield break; | |
yield return l.Head; | |
l = l.Tail; | |
} | |
} | |
} | |
public interface Maybe<T> { } | |
public class Nothing<T> : Maybe<T> | |
{ | |
public override string ToString() | |
{ | |
return "Nothing"; | |
} | |
} | |
public class Just<T> : Maybe<T> | |
{ | |
public T Value { get; private set; } | |
public Just(T value) | |
{ | |
Value = value; | |
} | |
public override string ToString() | |
{ | |
return Value.ToString(); | |
} | |
} | |
public interface Input<VALUE> { } | |
public class InputEOF<VALUE> : Input<VALUE> { } | |
public class InputEmpty<VALUE> : Input<VALUE> { } | |
public class InputEl<VALUE> : Input<VALUE> | |
{ | |
private VALUE val; | |
public InputEl(VALUE value) { val = value; } | |
public VALUE GetValue() { return val; } | |
} | |
public interface Iteratee<VALUE, out RESULT> | |
{ | |
} | |
public class Done<VALUE, RESULT> : Iteratee<VALUE, RESULT> | |
{ | |
private RESULT val; | |
private Input<VALUE> rem; | |
public Done(RESULT value, Input<VALUE> remaining) | |
{ | |
val = value; | |
rem = remaining; | |
} | |
public RESULT GetValue() { return val; } | |
public Input<VALUE> GetRemaining() { return rem; } | |
} | |
public class Cont<VALUE, RESULT> : Iteratee<VALUE, RESULT> | |
{ | |
private Func<Input<VALUE>, Iteratee<VALUE, RESULT>> fn; | |
public Cont(Func<Input<VALUE>, Iteratee<VALUE, RESULT>> f) | |
{ | |
fn = f; | |
} | |
public Func<Input<VALUE>, Iteratee<VALUE, RESULT>> GetFn() { return fn; } | |
} | |
public class Error<VALUE, RESULT> : Iteratee<VALUE, RESULT> | |
{ | |
private String message; | |
private Input<VALUE> input; | |
public Error(String message, Input<VALUE> input) | |
{ | |
this.message = message; | |
this.input = input; | |
} | |
public String GetMessage() { return message; } | |
public Input<VALUE> GetInput() { return input; } | |
} | |
public static class Exts | |
{ | |
public static void ForEach<T>(this IEnumerable<T> enumeration, Action<T> action) | |
{ | |
foreach (T item in enumeration) | |
{ | |
action(item); | |
} | |
} | |
public static T Match<T, VALUE>(this Maybe<VALUE> input | |
, Func<Just<VALUE>, T> just | |
, Func<Nothing<VALUE>, T> nothing) | |
{ | |
if (input is Just<VALUE>) return just(input as Just<VALUE>); | |
return nothing(input as Nothing<VALUE>); | |
} | |
public static T Match<T, VALUE>(this Input<VALUE> input | |
, Func<InputEOF<VALUE>, T> eof | |
, Func<InputEmpty<VALUE>, T> empty | |
, Func<InputEl<VALUE>, T> element) | |
{ | |
if (input is InputEOF<VALUE>) return eof(input as InputEOF<VALUE>); | |
if (input is InputEmpty<VALUE>) return empty(input as InputEmpty<VALUE>); | |
return element(input as InputEl<VALUE>); | |
} | |
public static T Match<T, VALUE, RESULT>(this Iteratee<VALUE, RESULT> step | |
, Func<Done<VALUE, RESULT>, T> done | |
, Func<Cont<VALUE, RESULT>, T> cont | |
, Func<Error<VALUE, RESULT>, T> error) | |
{ | |
if (step is Done<VALUE, RESULT>) return done(step as Done<VALUE, RESULT>); | |
if (step is Cont<VALUE, RESULT>) return cont(step as Cont<VALUE, RESULT>); | |
return error(step as Error<VALUE, RESULT>); | |
} | |
public static Maybe<RESULT> Run<VALUE, RESULT>(this Iteratee<VALUE, RESULT> i) | |
{ | |
return i.Match( | |
done => new Just<RESULT>(done.GetValue()), | |
cont => RunInt(cont.GetFn()(new InputEOF<VALUE>())), | |
error => { throw new Exception(); } | |
); | |
} | |
private static Maybe<RESULT> RunInt<VALUE, RESULT>(this Iteratee<VALUE, RESULT> i) | |
{ | |
return i.Match<Maybe<RESULT>, VALUE, RESULT>( | |
done => new Just<RESULT>(done.GetValue()), | |
cont => new Nothing<RESULT>(), | |
error => new Nothing<RESULT>() | |
); | |
} | |
public static Iteratee<VALUE, RESULT> Enumerate<VALUE, RESULT>(this Iteratee<VALUE, RESULT> i, List<VALUE> l) | |
{ | |
if (l.IsNil) return i; | |
return i.Match( | |
done => i, | |
cont => Enumerate(cont.GetFn()(new InputEl<VALUE>(l.Head)), l.Tail), | |
error => { throw new Exception(); } | |
); | |
} | |
} | |
static class Monad | |
{ | |
/* | |
Done x' _ -> Done x' str | |
Cont k -> k str | |
*/ | |
public static Iteratee<C, B> Bind<A, B, C>(this Iteratee<C, A> m, Func<A, Iteratee<C, B>> f) | |
{ | |
return m.Match( | |
done => f(done.GetValue()).Match<Iteratee<C, B>, C, B>( | |
done1 => new Done<C, B>(done1.GetValue(), done.GetRemaining()), | |
cont1 => cont1.GetFn()(done.GetRemaining()), | |
error1 => { throw new Exception("monad bug"); } | |
), | |
cont => new Cont<C, B>(inp => cont.GetFn()(inp).Bind(f)), | |
error => { throw new Exception("monad bug"); } | |
); | |
} | |
public static Iteratee<C, T> ToIteratee<T, C>(this T value) | |
{ | |
return new Done<C, T>(value, new InputEmpty<C>()); | |
} | |
public static Iteratee<Object, C> SelectMany<A, B, C>(this Iteratee<Object, A> a, Func<A, Iteratee<Object, B>> func, Func<A, B, C> select) | |
{ | |
return a.Bind(aval => | |
func(aval).Bind(bval => | |
select(aval, bval).ToIteratee<C, Object>())); | |
} | |
public static Func<A, C> ComposeDot<A, B, C>(Func<B, C> f, Func<A, B> g) | |
{ | |
return (x) => f(g(x)); | |
} | |
//f $ x = f x | |
public static B ComposeDollar<A, B>(Func<A, B> f, A x) | |
{ | |
return f(x); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment