我问了自己一个愚蠢的问题,现在已经绞尽脑汁几个小时没有结果。
假设您出于某种原因想在 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);
}
}