Статически типизированный корректный список минусов в C#

Я задал себе глупый вопрос и уже несколько часов ломаю себе голову безрезультатно.

Допустим, по какой-то причине вы хотите реализовать cons-ячейку в C# (десятого правила Гринспуна должно быть достаточно). Поскольку он находится в C#, вы хотите, чтобы он был статически типизирован. Что-то вроде этого должно быть достаточно:

interface ICons<T, U>
{
    T Left { get; }
    U Right { get; }
}

struct Cons<T, U> : ICons<T, U>
{
    public T Left { get; }
    public U Right { get; }

    public Cons(T left, U right)
    {
        Left = left;
        Right = right;
    }
}

struct Nil : ICons<Nil, Nil>
{
    public Nil Left => this;
    public Nil Right => this;
}

Теперь есть static void VisitList<T>(? list, Action<T> action) метод, который принимает правильно сформированный список T и делает что-то с каждым элементом. Хорошо сформированный список T это Nil или минус ячейка, которая имеет T как его левый элемент и правильно сформированный список T как его правильный элемент. Теперь мы можем заменить ? с реальным типом (да, представьте, что есть Either не-монада): static void VisitList<T, U>(Either<Nil, ICons<T, U>> list, Action<T> action) where U : Either<Nil, ICons<T, U>>,

Невозможный вопрос: как, черт возьми, вы строите значение, которое вы можете передать этому методу? Кто-нибудь может написать рабочий фрагмент? Остальная часть примера кода приведена ниже.

class Either<T, U>
{
    public bool IsRight { get; }
    public bool IsLeft => !IsRight;
    public T Left { get; }
    public U Right { get; }

    public Either(T left)
    {
        IsRight = false;
        Right = default(U);
        Left = left;
    }

    public Either(U right)
    {
        IsRight = true;
        Left = default(T);
        Right = right;
    }

    public static implicit operator Either<T, U>(T value) => new Either<T, U>(value);
    public static implicit operator Either<T, U>(U value) => new Either<T, U>(value);
}

class Program
{
    static void VisitList<T, U>(Either<Nil, ICons<T, U>> list, Action<T> action)
        where U : Either<Nil, ICons<T, U>>
    {
        while (list.IsRight) {
            action(list.Right.Left);
            list = list.Right.Right;
        }
    }

    static void Main(string[] args)
    {
        VisitList(/*put your well-formed cons list here*/, WriteLine);
        ReadKey(true);
    }
}

0 ответов

Другие вопросы по тегам