5

我问了自己一个愚蠢的问题,现在已经绞尽脑汁几个小时没有结果。

假设您出于某种原因想在 C# 中实现一个 cons 单元(Greenspun 的第十条规则就足够了)。由于它在 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并对每个元素执行某些操作。格式良好的列表 ofT是一个Nil或一个 cons 单元格,T其左侧元素和格式良好的列表 ofT作为其右侧元素。现在我们可以?用一个真实的类型替换(是的,想象一下有一个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);
    }
}
4

0 回答 0