Monad
There are many web sites to defining a monad so we will not repeat anything here other than to say that a Monad is an Applicative Functor that also has a bind
function that lifts a function that returns a new value in the context. There usually a discussion about Monad laws that accompany a Monad discussion. You can read about that almost anywhere on the web. bind
is also known as flatMap
or >>==
. bind
looks like map
which is why many people think of flatMap
first.
The last example went from a List[Int] to a List[String]. Since a scala List
is a Monad, you can do this. However, this example does not show what really happened. bind
(or flatMap
) is really a combination of a map
and a flatten
operation. Flatten joins together two Monads. In some circles, people say that bind
is really map
followed by a join
where join
combines, or collapses, two Monads. So the last statement actually does create a List(List("1"))
but then joins the two lists togethe using join/flatten
. flatten
takes a List within a List and returns a List which is why you see only the single list in res14
above. The scala function signature describes this as bind[A, B](fa: F[A])(f: A => F[B]): F[B]
. If bind
was to return an embedded list the return signature would have been much different e.g. F[F[B]]
.
Monad's have captivated many people's attention because you can use Monads to create some really interesting design patterns. Monad's can be seen as a wrapper around a value that, as a container, type constructor or its a way to chain methods together i.e. composition and as a way te sequence computations (using flatMap/bind).
There are many types of Monads. Each may be mapped to a programming concept like "potentially a value" via Option or "multiple return values/multiple outcomes" via a List.
If you want to read more about Monad's, search the web. Here's a link to Haskell's description All About Monads. There's also a description of what Monad's are not.
There are many uses for a Monad, but in fs2, a key use is to use a Monad as a container and map and flatMap into the container to alter the value inside without needing to know the details of how that value is represented. Because you do not need to make assumptions about how the contents of the container are represented, fs2 gains expressiveness. You can think of this gain in expressiveness (and abstraction) as a useful "one more levelof indirection."
Last updated