Monad
概要
M[A]の値を元にM[B]を生成できる能力
A monad is a mechanism for sequencing computations.
手続きを抽象化した構造
一つ一つのモナド直は計算機で、それらを合成してより複雑な計算機にできる
モナドは単なる自己関手の圏におけるモノイド対象だよ。何か問題でも?
一般的に合成可能ではない→MonadTransformer、Eff
文脈依存文法
https://gyazo.com/58461c1fdb578428366dd3e36cbaac63
Monads happen to be a sweet spot in this trade-off. They are flexible enough to model a wide range of behaviours and restrictive enough to give strong guarantees about those behaviours. However, there are situations where monads aren’t the right tool for the job. Sometimes we want Thai food, and burritos just won’t satisfy.
モナドは上の階層において計算能力と制限とでちょうど良いトレードオフにある
条件
flatMap
(F[A], A => F[B]) => F[B]
flatten
F[F[A]] => F[A]
pure
A=>F[A]
Left identity
pure(a).flatMap(func) == func(a)
モナドに値を入れても変換に影響を与えない
Right identity
m.flatMap(pure) == m
Associativity(結合法則)
m.flatMap(f).flatMap(g) == m.flatMap(x => f(x).flatMap(g))
Scala
code:scala
def flatMapA, B(value: FA)(func: A => FB): FB }
Cats
FlatMap型クラスに分離されている
flatMapに加えてtailRecMもプリミティブとして必要
def tailRecM[A, B](a: A)(f: A => F[Either[A, B]]): F[B]
モナドアクションの合成に関してスタックセーフにするために必要
iterateWhileM、foreverMなど再帰ループするモナド処理はtailReqMで実装しなければいけない
→flatMapで実装したら、自然にスタックセーフになるわけではないのでtailReqMで明示的に実装
foreverM
code:scala
def foreverMA, B(fa: FA): FB = { // allocate two things once for efficiency.
val leftUnit = Left(())
val stepResult: F[EitherUnit, B] = as(fa, leftUnit) tailRecM(())(_ => stepResult)
}
infinite effect loop. it will return an F<Nothing>.
asはfaをbとみなす→単純に置き換える
tailRecM[A, B](a: A)(f: A => F[Either[A, B]]): F[B]
tailRecMはB型になるまでループ(実装では末尾再帰が求められる)するからF<A>の作用が永遠に連鎖することになる
色々と処理を合成してfaの値を創って、そこからforevarMでループさせることでサーバー的な役割を実現したり
参照