定義
早速定義をみてみよう。
final case class OptionT[F[_], A](run: F[Option[A]])
OptionTはモナド変換子だ。なのでモナドをliftして合成できる。
val optList = List(1,2,3).liftM[OptionT]
// OptionT(List(Some(1), Some(2), Some(3)))
インスタンスの関数
map: A => B にする。
optList.map(_ + 1)
// OptionT(List(Some(2), Some(3), Some(4)))
flatMap: A => OptionT[F, B] にする。
optList.flatMap(x => List(x,x).liftM[OptionT])
// OptionT(List(Some(1), Some(1), Some(2), Some(2), Some(3), Some(3)))
forも。
for { a <- optList if a > 1 } yield a + 1
// OptionT(List(None, Some(3), Some(4)))
flatMapF: A => F[B] にする。
これはF(ここではList)を書き換える関数だ。
optList.flatMapF { case 1 => Nil case x => List(x) }
// OptionT(List(Some(2), Some(3)))
foldRight: 畳み込み。(Z)((A, Z) => Z): Z
optList.foldRight("a"){(x, a) => s"$x:$a"}
// 1:2:3:a
なぜfoldLeftがないんだろうか..?
traverse: OptionTをGでwrapする関数。
optList.traverse(x => Maybe.just(x + 1))
// Just(OptionT(List(Some(2), Some(3), Some(4))))
ap: F内の関数を適用する関数。
optList.ap(List((_:Int)+1).liftM[OptionT])
// OptionT(List(Some(2), Some(3), Some(4)))
以下Optionの関数と同じ感じ..
isDefined: Someならtrue
optList.isDefined
// List(true, true, true)
isEmpty: Noneならtrue
optList.isEmpty
// List(false, false, false)
filter: trueを返したらtrue
optList.filter(_ > 1)
// OptionT(List(None, Some(2), Some(3)))
fold: someの場合とnoneの場合を指定
optList.filter(_ > 1).fold(x=>x, -1)
// List(-1, 2, 3)
getOrElse: get or else
optList.filter(_ > 1).getOrElse(-1)
// List(-1, 2, 3)
exists: 存在するか
optList.exists(_ > 1)
// List(false, true, true)
forall: 全部あるか
optList.filter(_ > 1).forall(_ > 1)
// List(true, true, true)
orElse: Noneの場合
optList.filter(_ > 1).orElse(List(0).liftM[OptionT])
// OptionT(List(Some(0), Some(2), Some(3)))
toRight: EitherT(Right)に変換
optList.filter(_ > 1).toRight("err")
// EitherT(List(-\/(err), \/-(2), \/-(3)))
toLeft: EitherT(Left)に変換
optList.filter(_ > 1).toLeft("err")
// EitherT(List(\/-(err), -\/(2), -\/(3)))
オブジェクトの関数
optionT: OptionTを作成
OptionT.optionT[List](List(1.some))
// OptionT(List(Some(1)))
some: OptionTを作成(必ずSome)
OptionT.some[List, Int](1)
// OptionT(List(Some(1)))
none: OptionTを作成(必ずnone)
OptionT.none[List, Int]
// OptionT(List(None))
monadTell: Writer用
OptionT.monadTell[Writer, String, Int].writer("foo", 1)
// OptionT(WriterT((foo,Some(1))))
scalaでおなじみの関数ばかりだったので、目新しいものは少なかった。しかしモナドを合成できるのは面白い。次は別のモナド変換子を見てみるとしよう。