Created
July 4, 2017 07:51
-
-
Save ukitaka/ad45cbca1f589d8e2fa1269892b24e5c to your computer and use it in GitHub Desktop.
OptionT
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
trait Functor[F[_]] { | |
def map[A, B](fa: F[A])(f: A => B): F[B] | |
} | |
trait Monad[F[_]] extends Functor[F] { | |
def apply[A](a: A): F[A] | |
def flatMap[A, B](fa: F[A])(f: A => F[B]): F[B] | |
def map[A, B](fa: F[A])(f: A => B): F[B] = flatMap(fa)(a => apply(f(a))) | |
} | |
case class Id[A](a: A) | |
implicit val idMonad = new Monad[Id] { | |
def apply[A](a: A): Id[A] = Id(a) | |
def flatMap[A, B](fa: Id[A])(f: A => Id[B]): Id[B] = f(fa.a) | |
} | |
implicit val optionMonad = new Monad[Option] { | |
def apply[A](a: A): Option[A] = Some(a) | |
def flatMap[A, B](fa: Option[A])(f: A => Option[B]): Option[B] = fa.flatMap(f) | |
} | |
// Fについて、FunctorやMonadがあれば合成できる | |
final case class OptionT[F[_], A](value: F[Option[A]]) { | |
def map[B](f: A => B)(implicit F: Functor[F]): F[Option[B]] = | |
F.map(value)(_.map(f)) | |
def apply[A](a: A)(implicit M: Monad[F]): OptionT[F, A] = OptionT(M.apply(Some(a))) | |
def flatMap[B](f: A => F[Option[B]])(implicit M: Monad[F]): F[Option[B]] = | |
M.flatMap(value) { | |
case Some(a) => f(a) | |
case None => M.apply(None) | |
} | |
} | |
// OptionT自体をFunctor/Monadにする | |
implicit def optionTFunctor[F[_]](implicit F: Functor[F]) = new Functor[({ type R[A] = OptionT[F, A] })#R] { | |
def map[A, B](fa: OptionT[F, A])(f: A => B): OptionT[F, B] = OptionT(fa.map(f)) | |
} | |
implicit def optionTMonad[F[_]](implicit M: Monad[F]) = new Monad[({ type R[A] = OptionT[F, A] })#R] { | |
def apply[A](a: A): OptionT[F, A] = OptionT(M.apply(Some(a))) | |
def flatMap[A, B](fa: OptionT[F, A])(f: A => OptionT[F, B]): OptionT[F, B] = { | |
OptionT(fa.flatMap { a => f(a).value }) | |
} | |
} | |
val c = for { | |
a <- OptionT[Id, Int](Id(Some(1))) | |
b <- OptionT[Id, Int](Id(Some(2))) | |
} yield a + b |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment