Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@hodzanassredin
Created November 6, 2012 15:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hodzanassredin/4025522 to your computer and use it in GitHub Desktop.
Save hodzanassredin/4025522 to your computer and use it in GitHub Desktop.
iteratees in csharp
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