Most likely you will see a connection if you write a monad using unit and join instead of unit and bind :
trait Monoid[T] { def zero: T def combine: (T,T) => T } trait Monad[M[_]] { def unit[A]: A => M[A] def join[A]: M[M[A]] => M[A] }
The connection is Scala flatten and bind is Scala flatMap .
Note that to define a monad, simply using unit and flatten/join , you must also specify the map[A](m: M[A])(f: A => B): M[B] method. This is because the monad is actually an (endo) functor with two natural transformations, one and a union. Since this is a functor, it has map functionality. Depending on your code, map must be defined together with unit and join inside your Monad trait or inherited from some Functor trait, which will be extended by your Monad trait.
For completeness, let me outline all three possible ways to define a monad:
- unit + flatMap
- unit + flatten + map
- unit + compose
All three can be expressed using one of the other two. I will skip the code to demonstrate this, since it is not directly related to the question, but I can add it to the editing if necessary.
source share