Monads, a rethink

Stepping back from coding for a short while has allowed me to mull over the monad implementations in Woz.Functional and I have realised it is time for a rethink…

I have been through various implementations up to this point and all have followed a similar pattern. An interface, such as IMaybe<T>, and the concrete classes that back them. In the case of Maybe those are Some<T> : IMaybe<T> and None<T> : IMaybe<T>. This is all fine, the concrete classes are streamlined as they know the state which makes the implementation cleaner for each path.

The one thing though that this type of implementation has never addressed if the whole reason for Maybe and the other Monads in the first place, that is to make the types explicit. What is the point of something like Maybe if it is a reference type and hence can actually be null. The thing is is protecting us against is still possible.

The other issue I have always had is that Monads tend to have a short lifetime when you have a compositional workflow, being reference types means lots of heap churn and more load on the Garbage Collection.

The logical move here is to use value types via structs which removes both problems in one go. The Monads can’t be null and they are only on the heap when a member of a class so reduced object churn.

The downsides in this move are:

  • All operations need to determine state to select the path for an operation as structs are sealed.
  • For Monads such as Either<TR, TL> we have more data to pass around on the stack as we have the Left and Right values along with a bool as C# does not support discriminated unions… yet.

I believe this is the correct move though as it actually brings the Monad library closer to the goal, that being explicit types and side effects.

It will be a few days before I get into this refactor but the end results should be worth the .effort 🙂