2015年6月4日木曜日

scala関数型デザイン&プログラミング P108

Exercise 6.8
flatMapを実装し、それを使ってnonNegativeLessThanを実装せよ。
def flatmap[A,B](f:Rand[A])(g:A=>Rand[B]):Rand[B] = { rng =>
 val (a,rng2)=f(rng)
 g(a)(rng2)
 }
まず、fはRand[A]の型、つまり rng=>(a,rng2)を表す。したがって、val (a,rng2)=f(rng)となる。
つぎに、g:A=>Rand[B]より g(a)がRand[B]を表す。これにrng2を適用したg(a)(rng2)が返り値
そして、最終的に、flatMapの返り値は、{rng=>g(a)(rng2)}で、これはRand[B]

 def nonNegativeLessThan2(n:Int):Rand[Int] =
  flatMap(nonNegativeInt)(i=>
   val mod=i%n
   if (i+(n-1)-mod>=0)
    unit(mode)
   else
    nonNegativeLessThan2(n)
 )
  flatMapの第1引数は、Rand[A]なので、nonNegativeInt:Rand[Int]という関数でいい。
次に、第2引数は、A=>Rand[B]という型の関数。AはInt、つまり変数iとして、これを引数として
Rand[B]が返り値になるような関数を記述するとよい。
 この場合の返り値の計算は (i+(n-1)-mod)がTrueなら、unit(mode)つまり、rngが変化せず、(mode,rng)をそのまま返すような関数。falseならば、リトライする関数となる。

Exercise 6.9 flatMapを使ってmap,map2を再実装せよ。
def _map[A,B](s:Rand[A])(f:A=>B):Rand[B]=
 flatMap(s)(a=>unit(f(a))
 unitを使えばA=>Rand[B]の部分をうまく表せる

 def _map2[A,B,C](ra:Rand[A],rb:Rand[B])(f:(A,B)=>C):Rand[C] =
   flatMap(ra)(a => map(rb)(b => f(a, b)))
   こちらは解答例。 ra,rbのふたつ同時には変換は無理なので mapを使うとひとつずつできる。

0 件のコメント:

コメントを投稿