## The Worst Monad Tutorial... Except For All Those Others.

Excuse the tongue-in-cheek title of my recent post detailing my adventures in writing monads in C# 2.0. I believe I've finally nailed down the problems I was having, so thought I'd share. I'd welcome any corrections. :-)

## Comment viewing options

### Type-safe general monad interface in C#

Well, almost type-safe. It uses casts, but only for the monad implementors accessing internal state. The interface is very simple and strict, so it should be hard to make a mistake. Details here.

### Interestingly, it is

Unfortunately not, because C# cannot abstract over type constructors.

Interestingly, it is possible to simulate a very restricted class of higher-kindedly polymorphic functions in C# by adding sufficient extra type variables and related constraints. For example, one could encode

class Container c where
fst :: c a -> a

fstfst :: (Container c, Container d) => d (c a) -> a


by

interface Container<A> { A Fst(); }

A FstFst<DCA,CA,A>(DCA x)
where DCA : Container<CA>
where  CA : Container<A>


But clearly this pattern only applies to type signatures where the higher-kinded type variables are not applied to different arguments within the same signature. One could not encode something like, for example:

  join :: (Monad m) => m (m a) -> m a


so the class of functions that can be encoded is very limited, and as usual with C# there's a fair bit of syntactic noise.

### Really higher-kinded?

It seems to me that what you've simulated is much closer to this:

class Container c a | c -> a  where
fst :: c -> a

fstfst :: (Container c a, Container d c) => d -> a

Am I missing out on a subtlety?

### No, I don't think there is

No, I don't think there is any subtlety. The restricted class of functions are precisely those which can be written in the way you demonstrate using fundeps in (non-standard) Haskell.

### I believe you can encode

I believe you can encode join using the technique in my follow-up post.