| public interface IListupleVisitor
{
void Invoke<T>(T arg);
}
public interface L
{
void Apply(IListupleVisitor listupleVisitor);
}
public sealed class Nil : L
{
public static readonly Nil Value = new Nil();
private Nil() {}
public void Apply(IListupleVisitor listupleVisitor) {}
}
public interface L<out THead, out TTail> : L
where TTail : L
{
THead Head { get; }
TTail Tail { get; }
}
public sealed class Cons<THead, TTail> : L<THead, TTail> where TTail : L
{
private readonly THead head;
private readonly TTail tail;
public Cons(THead head, TTail tail)
{
this.tail = tail;
this.head = head;
}
public THead Head
{
get { return head; }
}
public TTail Tail
{
get { return tail; }
}
public void Apply(IListupleVisitor listupleVisitor)
{
listupleVisitor.Invoke(Head);
Tail.Apply(listupleVisitor);
}
}
public static class Listuple
{
public static L<THead, TTail> Add<THead, TTail>(this TTail tail, THead head)
where TTail : L
{
return new Cons<THead, TTail>(head, tail);
}
public static L<THead, TTail> Push<THead, TTail>(this TTail tail, THead head)
where TTail : L
{
return tail.Add(head);
}
public static TTail Pop<THead, TTail>(this L<THead, TTail> list, Action<THead> consume)
where TTail : L
{
consume(list.Head);
return list.Tail;
}
public struct SeedPair<T, TL>
where TL : L
{
public readonly T Value;
public readonly TL List;
public SeedPair(T value, TL list)
{
Value = value;
List = list;
}
}
public static SeedPair<T, TL> Seed<T, TL>(this TL list, T value)
where TL: L
{
return new SeedPair<T, TL>(value, list);
}
public static SeedPair<TOutput, TTail> Pop<THead, TTail, TInput, TOutput>(this SeedPair<TInput, L<THead, TTail>> pair,
Func<TInput, THead, TOutput> aggregate)
where TTail : L
{
return pair.List.Tail.Seed(aggregate(pair.Value, pair.List.Head));
}
public static TOutput Pop<THead, TInput, TOutput>(this SeedPair<TInput, L<THead, Nil>> pair,
Func<TInput, THead, TOutput> aggregate)
{
return aggregate(pair.Value, pair.List.Head);
}
}
|