Exercise 6.10 unit,map2,flatMap,sequenceの5つの関数を一般化せよ。
case class State[S, +A](run: S => (A, S)) {
def flatMap[B](f: A => State[S, B]): State[S, B] = State(s=> {
val (a,st)=run(s)
f(a)(st)
})
// runという関数は、S=>(A,S)なので、run(s)により(a,st)を返す
//f:A=>State[S,B]だから f(a)はState[S,B]すなわちS=>(A,S)という関数であり、引数は今の場合st:S
//をもってくるとよい。したがってf(a)(st)
def map[B](f: A => B): State[S, B] =
flatMap(a=> unit(f(a)) )
def map2[B,C](sb: State[S, B])(f: (A, B) => C): State[S, C] =
flatMap(a => sb.map(b =>f(a,b)))
//State[S,C] S=>(C,S)という関数が返値 b=>f(a,b)つまりb=>cをmapに適用する
// と State[S,B]がState[S,C]に変換される flatMap(f:A=>State[S,C]):State[S,C]という型になっている
}
object State {
def unit[S, A](a: A): State[S, A] =
State(s => (a, s))
def sequenceViaFoldRight[S,A](sas: List[State[S, A]]): State[S, List[A]] =
sas.foldRight(unit[S, List[A]](List()))((f, acc) => f.map2(acc)(_ :: _))
//ここで、folrRightを復習してみた。
//def foldRight[A,B](as:List[A],z:B)(f:(A,B)=>B):Bだった。
// (f, acc) => map2(f, acc)(_ :: _) では
// f.map2(acc)(_::_)が f:State[S,A]とacc:State[S,List[A]]を結合して、新たに State[S,List[A]]を返す
//fにはsas:List[State[S,A]]から State[S,A]をひとつずつ切り取ってくる感じ?けっこう難しい。
}
case classとobjectに分けて実装しているが、その理由など、基本的なことがまだよくわかってない。
0 件のコメント:
コメントを投稿