Skip to content

Instantly share code, notes, and snippets.

@phadej
Last active August 29, 2015 14:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save phadej/ef766774721df7245a69 to your computer and use it in GitHub Desktop.
Save phadej/ef766774721df7245a69 to your computer and use it in GitHub Desktop.

Calling monadic bind flatMap may cause some confusion. flatMap is very list (or container) specialised name which gives false intuition. Even worse is to call monadic join flatten. Monadic join isn't very good name either, if you drop monadic.

OTOH: flatten does flatten type structure, F[F[A]] => f[A], but I'm not sure how many of us think on the type-level first.

I'm very glad that in scalaz monadic bind is bind. Unfortunately Scala's for comprehension desugars into flatMap's, AFAIK.

One (a bit contrived) example: https://github.com/phadej/playground/blob/master/scala/src/main/scala/homogenicpair.scala

import homogenicpair.implicits._

val a: Tuple2[Int, Int] = (2, 3)
def f(x: Int): Tuple2[Int, Int] = (x, x * x)

val x = a flatMap f

// Exiting paste mode, now interpreting.

a: (Int, Int) = (2,3)
f: (x: Int)(Int, Int)
x: (Int, Int) = (2,9)

The flatMap I defined for Tuple2[A, A] obeys monad laws.


Assume (Scala) language evolved enough to support type level natural numbers (actually it is). Then we could have

trait Vec[N <: Nat, A]

So Vec[Zero, _] is isomorpic to Unit, Vec[Succ[Zero], A] is Id[A] Vec[_2, A] is Tuple2[A,A] and so on.

And it's possible to give monadic structure to Vec for every N. The ZipList structure:

// scalaz has a bit different definitions
def pure[A](x: A): Vec[N, A] = repeat[N](x)
def ap[A,B](f: Vec[N. A => B], x: Vec[N, A]): Vec[N, B] = zipWith[N]((ff, xx) => ff(xx), f, x)
def bind[A,B](f: Vec[N, A => Vec[N, B]], x: Vec[N, A]): Vec[N, B] = diag[N](x map f)
def diag[A](f: Vec[N, Vec[N, A]]): Vec[N, A] = ??? /* take elements on diagonal of N × N matrix */
//

Then if we take Vec[_2, Int] ≡ pair of Int's:

val a: Tuple2[Int, Int] = (1, 2)
def f(x: Int): Tuple2[Int, Int] = Tuple2(x, x * x)

val x: Tuple2[Int, Int] = a flatMap f // what is the result?
// it's Tuple2(1, 4)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment