Skip to content

Instantly share code, notes, and snippets.

@damienstanton
Last active August 29, 2015 14:12
Show Gist options
  • Select an option

  • Save damienstanton/a5c2fdd8875d26ad1646 to your computer and use it in GitHub Desktop.

Select an option

Save damienstanton/a5c2fdd8875d26ad1646 to your computer and use it in GitHub Desktop.
Learning Monads
// General monadic pattern
trait Monad[A] {
def map[B](f: A => B): Monad[B]
def flatMap[B](f: A => Monad[B]): Monad[B]
}
// Option Monad
sealed trait Option[A] {
def map[B](f: A => B): Option[B]
def flatMap[B](f: A => Option[B]): Option[B]
}
/*
* Further pattern using the option monad
*/
case class Some[A](a: A) extends Option[A] {
def map[B](f: A => B): Option[B] = new Some(f(a))
def flatMap[B](f: A => Option[B]): Option[B] = f(a)
}
case class None[A] extends Option[A] {
def map[B](f: A => B): Option[B] = new None
def flatMap[B](f: A => Option[B]): Option[B] = new None
}
// Inside
class Foo { def bar: Option[Bar] }
class Bar{ def baz: Option[Baz] }
class Baz { def compute: Int }
// More composed, but still hard to read...
def compute(maybeFoo: Option[Foo]): Option[Int] =
maybeFoo.flatMap { foo =>
foo.bar.flatMap { bar =>
bar.baz.map { baz =>
baz.compute
}
}
}
// Better
def computeAll(foos: List[Foo]): List[Int] =
for {
foo <- foos
bar <- bar.baz
results <- baz.computeAll
} yield results
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment