我问过自己一个愚蠢的问题,现在已经把我的大脑震撼了几个小时而没有结果。
假设您想要在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
列表并对每个元素执行某些操作。格式良好的T
列表是Nil
或cons小区,其左侧元素为T
,而T
格式正确。现在我们可以用真实类型替换?
(是的,假设有一个Either
非monad):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);
}
}