Skip to content

Instantly share code, notes, and snippets.

@missingfaktor
Created November 1, 2015 14:49
Show Gist options
  • Select an option

  • Save missingfaktor/571cd29ce357b2367b22 to your computer and use it in GitHub Desktop.

Select an option

Save missingfaktor/571cd29ce357b2367b22 to your computer and use it in GitHub Desktop.
package sudoku.console
object Monadology {
// Wear the function goggles.
val foo = 2 + 3
val bar = foo + 1
Math.min(foo, bar)
// Start seeing let bindings as functions!
def let[A, B](f: => A)(cont: A => B): B = cont(f)
let(2 + 3) { foo =>
let(foo + 1) { bar =>
Math.min(foo, bar)
}
}
// A, (A => B) => B
// Nulls
import java.util.{Map => JMap, HashMap => JHashMap, Arrays => JArrays}
val mappa = new JHashMap[Int, String] {
put(2, "two")
put(3, "three")
}
// REAL WORLD!!!!
// Nice code, but incorrect code
val x = mappa.get(2)
val y = mappa.get(x.length)
x.concat(y)
// Not so nice code, but correct code
val x1 = mappa.get(2)
if (x1 != null) {
val y1 = mappa.get(x.length)
if (y1 != null) {
x.concat(y)
} else {
null
}
} else {
null
}
// Null is barbaric. Let's use options.
val mappa1 = Map(2 -> "two", 3 -> "three")
// Not so nice code, even with Scala, but correct code
mappa1.get(2) match {
case Some(x) =>
mappa1.get(x.length) match {
case Some(y) => Some(x.concat(y))
case None => None
}
case None =>
None
}
// Let's abstract!
def ifNonNull[A, B](f: Option[A])(cont: A => Option[B]): Option[B] = {
f match {
case Some(a) => cont(a)
case None => None
}
}
ifNonNull(mappa1.get(2)) { x =>
ifNonNull(mappa1.get(x.length)) { y =>
Some(x.concat(y))
}
}
// Whoa. let and ifNonNull look similar!
// let : Id[A], (A => Id[B]) => Id[B]
// ifNonNull : Option[A], (A => Option[B]) => Option[B]
// Both let and ifNonNull "bind" things! How they do it varies.
trait Let[F[_]] {
def let[A, B](f: F[A])(g: A => F[B]): F[B]
def pull[A](a: A): F[A]
}
object Let {
implicit val optionLet = new Let[Option] {
override def let[A, B](f: Option[A])(g: (A) => Option[B]): Option[B] = f.flatMap(g)
override def pull[A](a: A): Option[A] = Some(a)
}
}
def kompose[A, B, C, F[_]](f: A => F[B])(g: B => F[C])(implicit let: Let[F]): A => F[C] = { a =>
let.let(f(a)) { b =>
let.let(g(b)) { c =>
let.pull(c)
}
}
}
// We captured the "notion of binding" in an anstraction named Let.
// Let -> Monad
// let -> bind, flatMap, (>>=)
// pull -> point, pure
// kompose -> Kleisli composition
// WAIT!!!
// Let has special syntax in almost every language, because it's so common.
// Monadic bind has special syntax in FP languages, because it's fucking common.
for {
x <- mappa1.get(2)
y <- mappa1.get(x.length)
} yield x.concat(y)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment