List+Tuple=Listuple
От: artelk  
Дата: 14.01.15 17:27
Оценка:
  Развлекался тут на досуге
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);
    }
}


  Пример использования
private static void Main()
{
    L<DateTime, L<double, L<string, L<int, Nil>>>> list = 
        Nil.Value.Add(42).Add("Hi").Add(3.1415927).Add(DateTime.Now);

    list.Pop(v => Console.WriteLine(v))
        .Pop(v => Console.WriteLine(v))
        .Pop(v => Console.WriteLine(v))
        .Pop(v => Console.WriteLine(v));

    var value = list.Seed("")
                    .Pop(Add)
                    .Pop(Add)
                    .Pop(Add)
                    .Pop(Add);
    Console.WriteLine(value);

    list.Apply(WriteLineListupleVisitor.Instance);
}

private static string Add<T>(string s, T v)
{
    return string.IsNullOrEmpty(s) ? v.ToString() : s + "; " + v;
}

private sealed class WriteLineListupleVisitor : IListupleVisitor
{
    public static readonly WriteLineListupleVisitor Instance = new WriteLineListupleVisitor();

    public void Invoke<T>(T arg)
    {
        Console.WriteLine("Type: {0}; Value: {1}", typeof(T).FullName, arg);
    }
}


Когда оно может быть полезным пока не придумал.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.