In a previous post I introduced monad transformers and since now we should have a good feeling about their usage and how they can be helpful.
Designing a monad transformer we decided to fix inner most monad. This decision was dictated by the fact that we couldn’t replace code dependent on internal representation of that inner most monad. I think that this step could not be as obvious as I expected to be. And now I will try to make it more clear.
Let’s try to bite the problem from different side. Assume that we can write
a monad transformer and know nothing about monads internal representation.
Let’s call it CMonad
(shorthand from ComposedMonad
).
Such a class could look like
1 2 3 4 5 6 7 8 |
|
Here F[_]
and G[_]
are higher kinded type representing outer and inner most monad.
Then a problem introduced in a previous post could be solved following
1 2 3 4 5 |
|
Of course it doesn’t work because we haven’t yet provided implementation for flatMap
and map
Let’s start with flatMap
. To make things clear a little I introduced a new
method flatMapF
and defined flatMap
in terms of flatMapF
1 2 3 4 5 6 7 8 9 10 11 |
|
In order to apply f : A => F[G[B]]
we need to extract A
from value: F[G[A]]
One attempt could end with following code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
|
Now we can apply f
with A
and we will get fgb : F[G[B]]
1 2 3 4 5 6 7 8 9 10 |
|
In order to make compiler happy we need to take one step more - extract
G[B]
from F[G[B]]
and return that value from inner most flatMap
.
This of course is not possible knowing only that F
and G
form a monad.
Another attempt can lead us to the code like
1 2 3 4 5 6 7 8 9 |
|
And now we need to extract F[G[B]]
from G[F[G[B]]]
. This also is not possible
if we know nothing about internal representation of G
.
All this leads us to the conclusion that we can’t write a monad transformer if we know nothing, about the monads.