Skip to content

Instantly share code, notes, and snippets.

@raymondtay
Created April 18, 2012 04:32
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 raymondtay/2411129 to your computer and use it in GitHub Desktop.
Save raymondtay/2411129 to your computer and use it in GitHub Desktop.
Simple Monad
// Functors appear to be type converters for type constructors
trait Functor[T[_]] {
def apply[A](x: A) : T[A]
// curried functions (a.k.a partially-applied functions)
def map[A,B](x: T[A])(f: A => B) : T[B]
}
// Monads are very good for flattening types
trait Monad[T[_]] {
def flatten[A](m : T[T[A]]) : T[A]
def flatMap[A,B](x: T[A])(f: A => T[B])(implicit fn: Functor[T]): T[B] =
flatten(fn.map(x)(f))
}
object MonadDemo extends App {
val listInt = List(List(1,2,3,4,5,6))
val converter = new Monad[List] {
// in the body, i'm cheating a little cos i'm using the
// method 'flatten' provided in Scala's List. You should
// guess it by now that Scala's collections are Monads.
def flatten[A](m : List[List[A]]) : List[A] = m.flatten
// i don't define the flatMap again because its already done
// in the Monad trait. The beauty of describing computations :)
}
// You need a type transformer aka Functor
// In this example, its a list of 'Int' to list of 'Double'
implicit val functorL = new Functor[List] {
def apply[Double](x: Double) : List[Double] = List(x)
def map[Int, Double](x: List[Int])(f: Int => Double) : List[Double] = {
for (i <- x ) yield f(i)
}
}
val listDouble = converter.flatMap(listInt)(i => for(j <- i) yield j.toDouble )
println("We're going to flatten a list of 'int' & convert to list of 'double'")
println("before -> " + listInt)
println("after -> " + listDouble)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment