As Aaron already said, the answer is no. The simplest example to see that you cannot always "come back" from a monad, in my opinion, is the case of the frequently called Maybe
monad or Option
. You can see an implementation in C# here: https://mikhail.io/2016/01/monads-explained-in-csharp/
I don't really know C# so I will avoid writing code and try to explain it with words.
To model computations that can fail we could use a data type that either is a value or it is nothing (think of an alternative to null
). The requirements for that datatype to be a monad are the following:
- If we have a computation that never fails, returning something of type
B
, then we can get an equivelent computation that returns Maybe<B>
.
This is the return
constructor, that simply wraps the value inside Maybe
.
- We can compose computations that might fail. How? Well, if the first one fails, everything fails. If it doesn't, then we pass the returned value to the next function. This is the behaviour of bind.
- We also need some laws to be valid, but let's forget about it for the sake of simplicity.
Consider the case where we compose two functions that might fail. Can we always get a value? Well, not always. We get a value when neither of the two functions have failed.
I will try to explain it with code now. You can correct me when I'm wrong.
So lets say we have maybe a value maybeValue
of type A
Maybe<A> maybeValue = ...;
And we have a function foo
that takes values of type A
.
Maybe<B> foo(A a) {...}
We want to pass maybeValue
to foo
. Monads let you do that without inspecting maybeValue
to see if it has or not a value. Yo do it like this:
Maybe<B> result = maybeValue.bind(foo)
Again: Can I always transform result
into something of type B
? I mean, does result
always contain a value? Well, no. Only when both maybeValue
and foo
were successful.