Applicative
概要
依存性のない計算
F[A]、F[B]の値を組み合わせることを可能にする(計算、作用を組み合わせることを可能にしている)→mapN
F[A]の値に応じてF[B]を構築できるMonadよりは弱い アクションをシンプルに組み合わせて最後の値を返すみたいな。
普通のプログラミングでは文をつらつらと書いていく場面をApplicativeで記述できる
IO.sleep(5.second) *> IO.println("hello") *> IO.delay("ok"): IO[String]
code:scala
sleep(5);
println("hello");
return "ok";
Applicativeインスタンスは一般に合成可能
ApplicativeなF[_]とG[_]とがあった場合、F[G[_]]もApplicativeになる
文脈自由文法
条件
ap/product
二つのコンテキスト値を独立して組み合わせる能力
def ap[A, B](ff: F[A => B])(fa: F[A]): F[B]
def product[A, B](fa: F[A], fb: F[B]): F[(A, B)]
pure
値をコンテキストに入れる能力
Associativity(結合法則)
組み合わせの順番に寄らず等しくなる
fa.product(fb).product(fc) ~ fa.product(fb.product(fc))
Left identity
pure(()).product(fa) ~ fa
Right identity
fa.product(pure(())) ~ fa
例
Validated
Webフォームみたいに全て入力してもらってエラーがある箇所は全てエラーメッセージと一緒にユーザーに示す
→Eitherでは以前の計算に依存できる故に一つのフォームが失敗すると以降は実行すらされない
cats
Semigroupal
二つの文脈を組み合わせることができる型クラス
code:scala
}
catsではSemigroupal,Functorを継承してApply
Applyを継承してApplicative
Scala
code:scala
trait Applicative[F_] extends FunctorF { def mapA, B(fa: FA)(f: A => B): FB = ap(pure(f))(fa) }
code:scala
(Option(123), Option("abc")).tupled
SemigroupalList.product(List(1, 2), List(3, 4)) (List(1, 2), List(3, 4), List(5,6)).tupled
//それぞれのListから一つずつ選ぶ組み合わせ 2^3
// Cartesian product(直積集合)
二つの文脈を組み合わせる
ListでのSemigroupalは(1,3,5)...みたいな感じで他の文脈値と交わった値が出来上がっている(直積集合)。これはApplicativeでの独立した組み合わせに反している。このような挙動なのはListがMonadであるから。そのMonadのflatMapでproductが実装されているから。