What is a Monad in Scala?

What has helped me is to think of a monad as a container with operations (map/flatMap/filter/foreach) that can act on the contents without extracting it first.

For instance, this function “opens” the option to get its content:

def display(msg: String, prompt: Option[String] = None) = {
  prompt match {
    case None => ()
    case Some(str) => print(str)
  }
  println(msg)
}

Contrast this with:

def display(msg: String, prompt: Option[String] = None) = {
  prompt foreach print
  println(msg)
}

where the option is told to print its content (if any).

I find it especially powerful with futures because in that case, there is no alternative: There is no way (short of using an additional thread) to “extract” the contents of a future that is still being computed asynchronously.

The beauty of Scala is the for/yield construct that results in code much easier to read than chained calls to map and flatMap:

val futureImage: Future[Image] = ...
val futureText: Future[Text] = ...
val futurePage: Future[Page] =
  for {
    image <- futureImage
    text <- futureText
  } yield makePage(image, text)

The Java equivalent is harder to read:

CompletionStage<Image> futureImage = ...
CompletionStage<Text> futureText = ...
CompletionStage<Page> futurePage =
  futureImage.thenCompose(image ->
    futureText.thenApply(text ->
      makePage(image, text)
    ));

(especially given than flatMap is called thenCompose and map is called thenApply on Java’s futures)

2 Likes