Skip to content

Instantly share code, notes, and snippets.

@derekjw
Created April 3, 2011 15:18
Show Gist options
  • Save derekjw/900477 to your computer and use it in GitHub Desktop.
Save derekjw/900477 to your computer and use it in GitHub Desktop.
Akka Future with a Monad result
package akka.examples
import scalaz._
import Scalaz._
import akka.actor._
import akka.dispatch.Future
import akka.scalaz.futures._
object Main extends App {
val result = for {
a <- FutureM(List(1,2,3))
b <- FutureM(List.range(1, a + 1))
c <- FutureM(List(2)) if b >= 2
d <- FutureM(List("a", "b", "c"))
} yield d + (b * c)
println(result.get)
}
sealed trait FutureM[M[_], A] extends NewType[Future[M[A]]] {
def map[B](f: A => B)(implicit t: Traverse[M]): FutureM[M, B] = new FutureM[M, B] {
val value = FutureM.this.value flatMap (v => t.traverse((a: A) => Future(f(a)), v))
}
def flatMap[B](f: A => FutureM[M, B])(implicit m: Monad[M], t: Traverse[M]): FutureM[M, B] = new FutureM[M, B] {
val value = FutureM.this.value flatMap (v => t.traverse(f(_: A).value,v).map(_.join))
}
def foreach(f: A => Unit)(implicit fe: Each[M]): Unit = value.foreach(_ foreach f)
def withFilter(f: A => Boolean)(implicit e: Empty[M], p: Pure[M], m: Monad[M], t: Traverse[M]): FutureM[M, A] =
this.flatMap(a => FutureM(if (f(a)) p.pure(a) else e.empty))
}
object FutureM {
def apply[M[_], A](m: => M[A]): FutureM[M, A] = new FutureM[M, A] {
val value = Future(m)
}
implicit def FutureMPure[M[_]: Pure]: Pure[({type λ[α]= FutureM[M, α]})#λ] = new Pure[({type λ[α]=FutureM[M, α]})#λ] {
def pure[A](a: => A) = new FutureM[M, A] {
val value = a.pure[M].pure[Future]
}
}
implicit def FutureMFunctor[M[_]: Traverse] = new Functor[({type λ[α]= FutureM[M, α]})#λ] {
def fmap[A, B](x: FutureM[M, A], f: A => B) = x map f
}
implicit def FutureMBind[M[_]: Traverse : Monad] = new Bind[({type λ[α]= FutureM[M, α]})#λ] {
def bind[A, B](x: FutureM[M, A], f: A => FutureM[M, B]) = x flatMap f
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment