Functors, Monads, Applicatives – can be so simple | de.velopmind | The Det about Programming
補足説明を加えて簡単に整理してみた。
(A => B) => (C[A] => C[B])
(A => C[B]) => (C[A] => C[B])
※標準ライブラリにはないがScalazで実装されてる
(C[A => B]) => (C[A] => C[B])
何らかの機能を持ったコンテナ型C(つまりMonad、例えばOption)の中身だけを変換するにはC[A] => C[B]という関数が必要となる。 例えば、Option[Int] => Option[String]とか、Option[Int] => Option[Int]とか。
手元にA => Bという関数があればFunctorの機能が使える。
val f: Int => String = x => x.toString
val n: Option[Int] = Some(1)
// (Int => String) => (Option[Int] => Option[String])を
// 関数:Int => Stringと値:Option[Int]に適用
n.map(f)
// Monadとしてfor式で書くなら
for {
a <- n
} yield f(a)
手元にA => C[B]という関数があればMonadの機能が使える。
val f: Int => Option[String] = x => Some(x.toString)
val n: Option[Int] = Some(1)
// (Int => Option[String]) => (Option[Int] => Option[String])を
// 関数:Int => Option[String]と値:Option[Int]に適用
n.flatMap(f)
// Monadとしてfor式で書くなら
for {
a <- n
b <- f(a)
} yield b
手元にC[A => B]という関数があればApplicativeの機能が使える。
import scalaz._, Scalaz._
val f: Option[Int => String] = Some(x => x.toString)
val n: Option[Int] = Some(1)
// (Option[Int => String]) => (Option[Int] => Option[String])を
// 関数:Option[Int => String]と値:Option[Int]に適用
Applicative[Option].ap(n)(f)
// 演算子を使うなら
n <*> f
// Monadとしてfor式で書くなら
for {
a <- n
g <- f
} yield g(a)