Skip to content

Instantly share code, notes, and snippets.

@pasviegas
Forked from huitseeker/MT.scala
Last active August 29, 2015 14:08
Show Gist options
  • Save pasviegas/8a90d031f53cbd26d791 to your computer and use it in GitHub Desktop.
Save pasviegas/8a90d031f53cbd26d791 to your computer and use it in GitHub Desktop.
object MyApp{
trait ApplicativeFunctor[A, F[A]] {
def apply[X](a:X): F[X]
def map[B](f: A => B): F[B]
}
trait Monad[A, M[A]] extends ApplicativeFunctor[A, M] {
def flatMMap[B](f: A => M[B]): M[B]
}
class OptionT[A, M[A]] (m:ApplicativeFunctor[Option[A], M]) extends ApplicativeFunctor[A, ({type T[X]=M[Option[X]]})#T] {
override def apply[X](a:X): M[Option[X]] = m(Option(a))
override def map[B](f: A => B): M[Option[B]] =
m map {(x: Option[A]) => x map f}
}
class OptionTM[A, M[A]](m:Monad[Option[A], M]) extends OptionT[A, M](m) with Monad[A, ({type T[X]=M[Option[X]]})#T] {
override def flatMMap [B] (f:A => M[Option[B]]) : M[Option[B]] =
m flatMMap {
case Some(z) => f(z)
case None => m(None)
}
}
abstract class MyTest{
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits._
// The unchanged future monad, but applied to Option[A]
class FutureOM[A](fut: Future[Option[A]]) extends Monad[Option[A], Future] {
def apply[X](a:X): Future[X] = Future { a }
def map[B](f: Option[A] => B): Future[B] = fut map f
def flatMMap[B](f: Option[A] => Future[B]): Future[B] = fut flatMap f
}
implicit def optionMF[A](f:Future[Option[A]]) = new OptionTM(new FutureOM(f))
trait FooService {
def find(id: Int): Future[Option[Int]]
}
trait BarService {
def find(id: Int): Future[Option[Int]]
}
trait QuuxService {
def find(id:Int): Future[Option[Int]]
}
val fooService: FooService
val barService: BarService
val quuxService: QuuxService
def finalRes(): Future[Option[Int]] =
fooService.find(1) flatMMap (barService.find _) flatMMap (quuxService.find _)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment