What are Monads?
A monad is a wrapper to a generic type T
which allows its manipulation but always returning a new wrapper.
Confusing? Let’s explain it.
In .NET we have nullable types. Once we want to admit a null value in a value type we can indicate that as follows:
int? x = null;
Simple. Right?
When we dig a bit to understand the code above we can see something interesting: a type called Nullable<T>
with the followig anathomy:
Nullable<int> x = null;
Console.WriteLine(x.HasValue);
//false
...
int? x = 10;
int? y = 20;
Console.WriteLine(x + y); //Same as x.Value + y.Value
//30
So we have a type acting as a wrapper to int
allowinfg operations as it was really one and also admiting null as a value and returning another Nullable<T>
.
It means that Nullable<T>
is a monad? Actually not, but let’s explore a little more.
More than a wrapper
Dispite the fact that to be a wrapper is a fundamental trait of a monad it don’t discribe one totally. Besides allowing the wrapping of some value a monad needs to be able to perform transformations which require a special function to that, the Bind
method in our case.
Let’s see Bind
in action with one of the most known monad, the Option<T>
type (a.k.a. Maybe
in some other languages). Let’s see the code:
var value = obj.Method() //returns 50
.ToOption<int>()
.Bind((v) => r > 0 ? "Higher than zero!" : "Lower os equals zero!")
.Contains("Higher than zero!");
Console.WriteLine(value);
//true
Notice the function Bind
. It operates on Option<int>
, turning it on an Option<string>
which in turn once chainned to Contains
returns a bool bool
.
Although Bind
is a requirement to define a monad it is totally possible to have several others to manipulate the wrapped value simplifying its use (as Contains
above do).
Flattening
Mark Seemann, on his series about monads says a monad is a functor you can flatten.
That means that every monad needs to be able to return a wrapped monad by a method called Flatten
.
Let’s see another simples sample also with Option<T>
:
var option = Option.Some<Option<int>>(obj.Method()); //returns Option<int> (10)
Console.Write(option.Flatten());
//10
The code above represents an Option<T>
which could wrap another Option<T>
, the obj.Method()
return and to get it the Flatten
method must be called, allowing so the inner value to be accessed (10 in this case).
Once we have this understanding, let’s install Moonad and know a bit more of each available monad.