I asked myself a stupid question and have been waving my brain for several hours without any results.
Suppose you want to implement a cons cell in C # for some reason (the tenth Greenspun rule should be enough). Since it is in C #, you want it to be statically typed. Something like this should be enough:
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; }
Now there is a static void VisitList<T>(? list, Action<T> action)
method static void VisitList<T>(? list, Action<T> action)
, which takes a correctly formed list T
and does something for each element. A well-formed list T
is a Nil
or cons cell that has T
as its left element and a well-formed list T
as its right element. Now can we replace ?
on the real type (yes, imagine that Either
non-monad exists): static void VisitList<T, U>(Either<Nil, ICons<T, U>> list, Action<T> action) where U : Either<Nil, ICons<T, U>>
.
Impossible question: how do you build the value that you can pass to this method? Can someone write a working snippet? The rest of the sample code follows.
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(, WriteLine); ReadKey(true); } }