Monads explained (sort of) to a C# developer

August 2015

A monad is a fancy word for a generic type of the form MyMonad<T> (a generic type of arity 1).

A monad is special because it adds ‘special powers’ to the T that it wraps. These ‘special powers’ won’t sound very special to an imperative programmer, so you have to squint to see them but bear with me.

The trick with monads comes when you want to play with the T values, because they are inside another type. C# introduced language changes to make dealing with values inside these monads easier:

In languages like Haskell or F#, you have a general purpose way to define your own monads and define how to play with the values inside them. This is accomplished by defining two methods, usually called Return and Bind:

// Return lets you put a T inside the monad:
public static MyMonad<T> Return<T>(T value);

// Bind lets you get a take a MyMonad<T>, get at the T inside it,
// and turn it into a MyMonad<U>:
public static MyMonad<U> Bind<T, U>(MyMonad<T> value, Func<T, MyMonad<U>> operation);

In Haskell, these signatures look more or less like:

class Monad m where
  return :: a -> m a
  bind :: m a -> (a -> m b) -> m b

For example, Return lets you make a Task<string> from a string; Bind lets you take the string out of Task<string>, and turn it into a Task<UIImage>.

Monads are used extensively in functional programming to add ‘special powers’ like exceptions, async, state, logging, etc. to the exact regions of your code where you need them. Haskell, for example, is a much smaller language than C# because it doesn’t allow values to be null, it doesn’t allow mutation, it doesn’t have exceptions, and it doesn’t have LINQ; however, you can define these features (and more–e.g. massively parallel cloud computing) with monads and use them precisely.