Rosetta Monad Did It Again

Let e be an expression (e.g. x*x), m a monad instance instance (e.g. [1, 2, 3]) and M its type (list here).
Here is a small translation table, found buried in Memphis under a pill of pizza boxes:

Haskell, list comprehension [ e | x <- m ]
Haskell, do notation1 do {x <- m; return (e)}
Haskell, bind m >>= \x -> return (e)
Scala, yield for (x <- m) yield e
Scala, flatMap m.flatMap(x => M(e))
Scala, map m.map(x => e)

In the same spirit, let’s paint the monad laws in different colors.

Left identity Right identity Associativity
Haskell, list comprehension [ x | x <- m] ≡ m
Haskell, do notation do {x <- [a]; f x} ≡ f a do {x <- m ; x} ≡ m do {y <- do {x <- m; f x } g y} ≡ do { x <- m; do { y <- f x; g y }}2
Haskell, bind return a >>= f ≡ f a m >>= return ≡ m (m >>= f) >>= g ≡ m >>= (\x -> f x >>= g)
Scala, yield for (x <- m) yield x ≡ m
Scala, flatMap M(a).flatMap(f) ≡ f a m.flatMap(M) ≡ m m.flatMap(f).flatMap(g) ≡ m.flatMap(x => f(x).flatMap(g))
References: docs.scala-lang, wiki.haskell

MetaPostNote:
  • Find a proper way to have a nice style from markdown.
  • Link or embed runnable code.
Written with StackEdit. Messed up in the process.




  1. Although optional, the braces make clear that the scope of dois the whole block. ↩︎
  2. Equivalent to do { x <- m; y <- f x; g y } ↩︎

Comments