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.

scala> val m = Monad[List]
val m = Monad[List]
m: scalaz.Monad[List] = scalaz.std.ListInstances$$anon$1@1f8d2783

scala> m.map(List(1))(_+1)
m.map(List(1))(_+1)
res43: List[Int] = List(2)

scala> m.bind(List(1)){i:Int => List(i.toString)}
res14: List[String] = List(1)

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