Scala関数型デザイン&プログラミングを読んでいく

中途半端に読みかけになっている本書を読み進めていく。個人用のメモなので他者が読んで役に立つスクラップではないと思います。

上の記事を参考にpullしてきたリポジトリから始めても良いが、勉強がてらsbtでプロジェクト作成するところからやってみる。
関数型ライブラリを実装していき、テストコードを作成・実行までできるようにする雛形を作成するところまで。

sbtやJDKはすでに導入済みのはず

- docker-composeで作成する

このあたりを参考にしつつリポジトリ作成

3章関数型プログラミングのデータ構造
関数型データ構造は、当然ながら、純粋関数のみを使って操作されます。
package datastructures
sealed trait List[+A]
case object Nil extends List[Nothing]
case class Cons[+A](head: A, tail: List[A]) extends List[A]
object List {
def sum(ints: List[Int]): Int = ints match {
case Nil => 0
case Cons(x, xs) => x + sum(xs)
}
def product(ds: List[Double]): Double = ds match {
case Nil => 1.0
case Cons(0.0, _) => 0.0
case Cons(x, xs) => x * product(xs)
}
def apply[A](as: A*): List[A] =
if (as.isEmpty) Nil
else Cons(as.head, apply(as.tail: _*))
}

上のList[+A]
という記述で出てきた変位アノテーションの役割を果たす+
について。変位とは。
変位
ほぼ参照記事をなぞっているだけだが、忘れやすいので一旦まとめる。
非変
型A
= B
の時のにみ、型パラメータを持ったクラスGにおいて
val : G[A] = G[B]
のような代入が許される。変位アノテーション(List[+A]
の+
など`がないときはデフォルトでこの非変として扱われる。
共変(covariant)
型A
がB
を継承している時にのみ、
val : G[B] = G[A]
のような代入が許される。(言い換えれば、A
がB
の部分型である場合、G[A]
はG[B]
の部分型となる)
sclaaではクラス定義時にclass G[+A]
のように型パラメータの前に+
をつけると共変として宣言される。
反変(contravariant)
共変の逆で、
型A
がB
を継承している時にのみ、
val : G[A] = G[B]
のような代入が許される。(言い換えれば、A
がB
の部分型である場合、G[B]
はG[A]
の部分型となる)
sclaaではクラス定義時にclass G[-A]
のように型パラメータの前に-
をつけると共変として宣言される。
反変が使われる主な例としては関数の型がある。
val x1: A => AnyRef = B => AnyRef型の値
x1(A型の値)
のような関数が成功するには、反変の性質を持っている必要がある。(つまりAがBの部分型である必要があり、逆は成り立たない)

Exercise 3.2
my impl
def tail[A](l: List[A]): List[A] = l match {
case Nil => Nil
case Cons(x, xs) = xs
}
answer
def tail[A](l: List[A]): List[A] =
l match {
case Nil => sys.error("tail of empty list")
case Cons(_,t) => t
}

Exercise 3.3
def setHead[A](l: List[A], h: A): List[A] = l match {
case Nil => sys.error("setHead of empty list")
case Cons(_,t) => Cons(h, t)
}

Exercise 3.4
my impl
def drop[A](l: List[A], n: Int): List[A] = n match {
case m if m < 0 => sys.error("n should be positive.")
case 0 => l
case m => l match {
case Nil => sys.error("drop of empty list")
case Cons(x, xs) => drop(xs, n - 1)
}
}
answer
/*
Again, it's somewhat subjective whether to throw an exception when asked to drop more elements than the list contains. The usual default for `drop` is not to throw an exception, since it's typically used in cases where this is not indicative of a programming error. If you pay attention to how you use `drop`, it's often in cases where the length of the input list is unknown, and the number of elements to be dropped is being computed from something else. If `drop` threw an exception, we'd have to first compute or check the length and only drop up to that many elements.
*/
def drop[A](l: List[A], n: Int): List[A] =
if (n <= 0) l
else l match {
case Nil => Nil
case Cons(_,t) => drop(t, n-1)
}
一般的な実装としては、リストがNilだった場合も例外を投げることはない、とのコメント
マイナスの引数が与えられた場合も必要なさそう

Exercise 3.6
my impl
def init[A](l: List[A]): List[A] = l match {
case Nil => Nil
case Cons(x, Nil) => Nil
case Cons(x, xs) => Cons(x, init(xs))
}
def init[A](l: List[A]): List[A] =
l match {
case Nil => sys.error("init of empty list")
case Cons(_,Nil) => Nil
case Cons(h,t) => Cons(h,init(t))
}

カリー化による型推論の改善
def dropWhile[A](l :List[A]), f: A => Boolean): List[A]
のようなシグネチャだと、
val xs: List[Int] = List(1,2,3,4,5)
val ex1 = dropWhile(xs, (x: Int) => x < 4)
のように引数で渡す無名関数の引数x
の型を指定する必要がある。
本来これはxsがList[Int]
型であることから推測できるべきであるので、
def dropWhile[A](as: List[A])(f: A => Boolean): List[A] =
as match {
case Cons(h, t) if(h) => dropWhile(t)(f)
case _ => as
のように引数をグループ化(カリー化)することで、
関数定義に複数の引数グループが含まれている場合、型情報はこれらのグループを左から右へ流れます
なので2つめの引数で型推論が効くようになり
val xs: List[Int] = List(1,2,3,4,5)
val ex1 = dropWhile(xs)(x => x < 4)
のように実行できるようになる

Exercise 3.7
foldRightは右からの畳み込みで一度全ての要素を展開したのちに右から実行されるので、途中で再帰を中止できない
Exercise 3.8
上の特徴からリストの再生成(mapのような処理)に使われる。
Exercise 3.9
def length[A](as: List[A]): Int = foldRight(as, 0)((_, acc) => acc + 1)

Exercise 3.12
my impl
def reverse[A](l: List[A]): List[A] =
foldLeft(l, Nil: List[A])((b, a) => a match {
case Nil => b
case x => Cons(x, b)
})
テストは通った。foldLeftの最初のアキュムレータに型List[A]
を指定しないとNilに固定されてしまってダメだった。
answer
def reverse[A](l: List[A]): List[A] = foldLeft(l, List[A]())((acc,h) => Cons(h,acc))
accumulatorをList[A]()
で初期化していたのと、foldLeft はそもそも引数にNil
が渡された時はaccをそのまま返すので、パターンマッチング の部分が必要なかった。

Excercise 3.13
/*
The implementation of `foldRight` in terms of `reverse` and `foldLeft` is a common trick for avoiding stack overflows when implementing a strict `foldRight` function as we've done in this chapter. (We'll revisit this in a later chapter, when we discuss laziness).
The other implementations build up a chain of functions which, when called, results in the operations being performed with the correct associativity. We are calling `foldRight` with the `B` type being instantiated to `B => B`, then calling the built up function with the `z` argument. Try expanding the definitions by substituting equals for equals using a simple example, like `foldLeft(List(1,2,3), 0)(_ + _)` if this isn't clear. Note these implementations are more of theoretical interest - they aren't stack-safe and won't work for large lists.
*/
def foldRightViaFoldLeft[A,B](l: List[A], z: B)(f: (A,B) => B): B =
foldLeft(reverse(l), z)((b,a) => f(a,b))
def foldRightViaFoldLeft_1[A,B](l: List[A], z: B)(f: (A,B) => B): B =
foldLeft(l, (b:B) => b)((g,a) => b => g(f(a,b)))(z)
def foldLeftViaFoldRight[A,B](l: List[A], z: B)(f: (B,A) => B): B =
foldRight(l, (b:B) => b)((a,g) => b => g(f(b,a)))(z)
// Here is the same function with much more description
def foldLeftViaFoldRight_1[A,B](as: List[A], outerIdent: B)(combiner: (B, A) => B): B = {
// foldLeft processes items in the reverse order from foldRight. It's
// cheating to use reverse() here because that's implemented in terms of
// foldLeft! Instead, wrap each operation in a simple identity function to
// delay evaluation until later and stack (nest) the functions so that the
// order of application can be reversed. We'll call the type of this
// particular identity/delay function BtoB so we aren't writing B => B
// everywhere:
type BtoB = B => B
// Here we declare a simple instance of BtoB according to the above
// description. This function will be the identity value for the inner
// foldRight.
def innerIdent:BtoB = (b:B) => b
// For each item in the 'as' list (the 'a' parameter below), make a new
// delay function which will use the combiner function (passed in above)
// when it is evaluated later. Each new function becomes the input to the
// previous function (delayFunc).
//
// This much is just the type signature
// ,-------^-------.
def combinerDelayer:(A, BtoB) => BtoB =
(a: A, delayFunc: BtoB) => (b:B) => delayFunc(combiner(b, a))
// `----------v---------' `----------------v---------------'
// Paramaters The returned function
// Pass the original list 'as', plus the simple identity function and the
// new combinerDelayer to foldRight. This will create the functions for
// delayed evaluation with an combiner inside each one, but will not
// apply any of those functions.
def go:BtoB = foldRight(as, innerIdent)(combinerDelayer)
// This forces all the evaluations to take place
go(outerIdent)
}
/*
Here is a sample run for further illustration purposes
foldLeftViaFoldRight_1(List(1,2,3), Nil:List[Int])((b:B, a:A) => Cons(a, b))
Becomes:
foldRight(List(1,2,3), innerIdent)(combinerDelayer)(Nil)
Becomes:
def delay3(b:B) = innerIdent(combiner(b, 3))
def delay2(b:B) = delay3(combiner(b, 2))
def delay1(b:B) = delay2(combiner(b, 1))
delay1(Nil)
Becomes:
def delay3(b:B) = innerIdent(combiner(b, 3))
def delay2(b:B) = delay3(combiner(b, 2))
delay2(combiner(Nil, 1))
Becomes:
def delay3(b:B) = innerIdent(combiner(b, 3))
delay3(combiner(combiner(Nil, 1), 2))
Becomes:
innerIdent(combiner(combiner(combiner(Nil, 1), 2), 3))
Becomes:
combiner(combiner(combiner(Nil, 1), 2), 3)
Becomes:
combiner(combiner(Cons(1,Nil), 2), 3)
Becomes:
combiner(Cons(2,Cons(1,Nil)), 3)
Becomes:
Cons(3,Cons(2,Cons(1,Nil)))
Voila!
Alternate Route:
def delay3(b:B) = innerIdent(combiner(b, 3))
def delay2(b:B) = delay3(combiner(b, 2))
def delay1(b:B) = delay2(combiner(b, 1))
delay1(Nil)
Becomes:
def delay2(b:B) = innerIdent(combiner(combiner(b, 2), 3))
def delay1(b:B) = delay2(combiner(b, 1))
delay1(Nil)
Equivalent:
def delay1(b:B) = innerIdent(combiner(combiner(combiner(b, 1), 2), 3))
delay1(Nil)
Equivalent:
((b:B) => innerIdent(combiner(combiner(combiner(b, 1), 2), 3)))(Nil)
Equivalent:
innerIdent(combiner(combiner(combiner(Nil, 1), 2), 3))
*/

Exercise 3.14
my impl
def append2[A](a1: List[A], a2: List[A]): List[A] =
foldRight(a1, a2)((a, b) => a match {
case Nil => b
case x => Cons(x, b)
})
answer
def appendViaFoldRight[A](l: List[A], r: List[A]): List[A] =
foldRight(l, r)(Cons(_,_))
よりシンプルだった

Exercise 3.15
my impl
def flat[A](l: List[List[A]]): List[A] =
foldRight(l, List[A]())((a, b) => append2(a,b))
answer
/*
Since `append` takes time proportional to its first argument, and this first argument never grows because of the right-associativity of `foldRight`, this function is linear in the total length of all lists. You may want to try tracing the execution of the implementation on paper to convince yourself that this works.
Note that we're simply referencing the `append` function, without writing something like `(x,y) => append(x,y)` or `append(_,_)`. In Scala there is a rather arbitrary distinction between functions defined as _methods_, which are introduced with the `def` keyword, and function values, which are the first-class objects we can pass to other functions, put in collections, and so on. This is a case where Scala lets us pretend the distinction doesn't exist. In other cases, you'll be forced to write `append _` (to convert a `def` to a function value) or even `(x: List[A], y: List[A]) => append(x,y)` if the function is polymorphic and the type arguments aren't known.
*/
def concat[A](l: List[List[A]]): List[A] =
foldRight(l, Nil:List[A])(append)
命名等違ったもののOK

Exercise 3.16
my impl
def addOne(l: List[Int]): List[Int] =
foldRight(l, List[Int]())((a: Int, b) => Cons(a + 1, b))
foldRight(l, List[Int]())(Cons(_ + 1, _))
だと型推論が効かない?のかエラーが出た。
answer
def add1(l: List[Int]): List[Int] =
foldRight(l, Nil:List[Int])((h,t) => Cons(h+1,t))

Exercise 3.17
my impl
def doubleToString(l: List[Double]): List[String] =
foldRight(l, List[String]())((a, b) => Cons(a.toString, b))
answer
def doubleToString(l: List[Double]): List[String] =
foldRight(l, Nil:List[String])((h,t) => Cons(h.toString,t))

Exercise 3.18
my impl
def map[A,B](as: List[A])(f: A => B): List[B] =
foldRight(as, Nil: List[B])((h, t) => Cons(f(h), t))
answer
/*
A natural solution is using `foldRight`, but our implementation of `foldRight` is not stack-safe. We can use `foldRightViaFoldLeft` to avoid the stack overflow (variation 1), but more commonly, with our current implementation of `List`, `map` will just be implemented using local mutation (variation 2). Again, note that the mutation isn't observable outside the function, since we're only mutating a buffer that we've allocated.
*/
def map[A,B](l: List[A])(f: A => B): List[B] =
foldRight(l, Nil:List[B])((h,t) => Cons(f(h),t))
def map_1[A,B](l: List[A])(f: A => B): List[B] =
foldRightViaFoldLeft(l, Nil:List[B])((h,t) => Cons(f(h),t))
def map_2[A,B](l: List[A])(f: A => B): List[B] = {
val buf = new collection.mutable.ListBuffer[B]
def go(l: List[A]): Unit = l match {
case Nil => ()
case Cons(h,t) => buf += f(h); go(t)
}
go(l)
List(buf.toList: _*) // converting from the standard Scala list to the list we've defined here
}
スタックセーフを防ぐため(素直な実装のfoldRightは要素が多いとオーバーフローする可能性がある)の実装が示されている

Exercise 3.19
my impl
def filter[A](as: List[A])(f: A => Boolean): List[A] =
foldRight(as, List[A]())((h, t) => if (f(h)) Cons(h, t) else t)
answer
/*
The discussion about `map` also applies here.
*/
def filter[A](l: List[A])(f: A => Boolean): List[A] =
foldRight(l, Nil:List[A])((h,t) => if (f(h)) Cons(h,t) else t)
def filter_1[A](l: List[A])(f: A => Boolean): List[A] =
foldRightViaFoldLeft(l, Nil:List[A])((h,t) => if (f(h)) Cons(h,t) else t)
def filter_2[A](l: List[A])(f: A => Boolean): List[A] = {
val buf = new collection.mutable.ListBuffer[A]
def go(l: List[A]): Unit = l match {
case Nil => ()
case Cons(h,t) => if (f(h)) buf += h; go(t)
}
go(l)
List(buf.toList: _*) // converting from the standard Scala list to the list we've defined here
}

Exercise 3.20
my impl
def flatMap[A,B](as: List[A])(f: A => List[B]): List[B] =
concat(map(as)(f))
answer
/*
This could also be implemented directly using `foldRight`.
*/
def flatMap[A,B](l: List[A])(f: A => List[B]): List[B] =
concat(map(l)(f))

Exercise 3.21
my impl
def filterViaFlatMap[A](as: List[A])(f: A => Boolean): List[A] =
flatMap(as)(a => if (f(a)) List(a) else Nil)
answer
def filterViaFlatMap[A](l: List[A])(f: A => Boolean): List[A] =
flatMap(l)(a => if (f(a)) List(a) else Nil)

Exercise 3.22
my impl
def plusEachElement(l1: List[Int], l2: List[Int]): List[Int] = (l1, l2) match {
case (Cons(h, t), Cons(hh, tt)) => Cons(h + hh, plusEachElement(t, tt))
case (x, Nil) => x
case (Nil, x) => x
case _ => Nil
}
answer
/*
To match on multiple values, we can put the values into a pair and match on the pair, as shown next, and the same syntax extends to matching on N values (see sidebar "Pairs and tuples in Scala" for more about pair and tuple objects). You can also (somewhat less conveniently, but a bit more efficiently) nest pattern matches: on the right hand side of the `=>`, simply begin another `match` expression. The inner `match` will have access to all the variables introduced in the outer `match`.
The discussion about stack usage from the explanation of `map` also applies here.
*/
def addPairwise(a: List[Int], b: List[Int]): List[Int] = (a,b) match {
case (Nil, _) => Nil
case (_, Nil) => Nil
case (Cons(h1,t1), Cons(h2,t2)) => Cons(h1+h2, addPairwise(t1,t2))
}
少し違った。片方しか要素がなくなった時点でNilを返している

Exercise 3.23
my impl
def zipWith[A, B](l1: List[A], l2: List[A])(f: (A, A) => B): List[B] = (l1, l2) match {
case (Nil, _) => Nil
case (_, Nil) => Nil
case (Cons(h1, t1), Cons(h2, t2)) => Cons(f(h1, h2), zipWith(t1, t2)(f))
}
answer
/*
This function is usually called `zipWith`. The discussion about stack usage from the explanation of `map` also applies here. By putting the `f` in the second argument list, Scala can infer its type from the previous argument list.
*/
def zipWith[A,B,C](a: List[A], b: List[B])(f: (A,B) => C): List[C] = (a,b) match {
case (Nil, _) => Nil
case (_, Nil) => Nil
case (Cons(h1,t1), Cons(h2,t2)) => Cons(f(h1,h2), zipWith(t1,t2)(f))
}
確かに、一般化した形態で考えると二つのリストの要素の型は同一である必要はなかった。

p53
標準ライブラリのリストについて説明している項で右結合に関する記述が参考になったので引用
Scalaでは、名前が
:
で終わるメソッドは全て右結合である。つまり、x::xs
という式は、実際にはxs.::(x)
というメソッド呼び出しであり、データコンストラクタ::(x,xs)
を呼び出す。
リストの場合は要素を追加するのに先頭に追加していくのが普通なので、右結合が使われるのも納得がいく

Exercise 3.24
my impl
def hasSubsequence[A](sup: List[A], sub: List[A]): Boolean = {
def startsWith(p: List[A], b: List[A]): Boolean = (p, b) match {
case (Cons(h1, _), Cons(h2, Nil)) if (h1 == h2) => true
case (Cons(h1, t1), Cons(h2, t2)) if (h1 == h2) => startsWith(t1, t2)
case _ => false
}
(sup, sub) match {
case (Cons(h1, t1), Cons(_, t2)) => startsWith(sup, sub) || hasSubsequence(t1, sub)
case _ => false
}
}
answer
/*
There's nothing particularly bad about this implementation,
except that it's somewhat monolithic and easy to get wrong.
Where possible, we prefer to assemble functions like this using
combinations of other functions. It makes the code more obviously
correct and easier to read and understand. Notice that in this
implementation we need special purpose logic to break out of our
loops early. In Chapter 5 we'll discuss ways of composing functions
like this from simpler components, without giving up the efficiency
of having the resulting functions work in one pass over the data.
It's good to specify some properties about these functions.
For example, do you expect these expressions to be true?
(xs append ys) startsWith xs
xs startsWith Nil
(xs append ys append zs) hasSubsequence ys
xs hasSubsequence Nil
*/
@annotation.tailrec
def startsWith[A](l: List[A], prefix: List[A]): Boolean = (l,prefix) match {
case (_,Nil) => true
case (Cons(h,t),Cons(h2,t2)) if h == h2 => startsWith(t, t2)
case _ => false
}
@annotation.tailrec
def hasSubsequence[A](sup: List[A], sub: List[A]): Boolean = sup match {
case Nil => sub == Nil
case _ if startsWith(sup, sub) => true
case Cons(_,t) => hasSubsequence(t, sub)
}
自分の実装ではstartsWith
を関数内関数ではなく別関数として分けたのと、Nilをサブシークエンスとして認めていない点が間違っている。

ここからツリー構造
Exersize 3.25
my impl
def size[A](tree: Tree[A]): Int = tree match {
case Leaf(_) => 1
case Branch(left, right) => 1 + size(left) + size(right)
}
answer
def size[A](t: Tree[A]): Int = t match {
case Leaf(_) => 1
case Branch(l,r) => 1 + size(l) + size(r)
}

Exercise 3.26
my impl
def maximum(t: Tree[Int]): Int = t match {
case Leaf(v) => v
case Branch(l, r) => maximum(l).max(maximum(r))
}
answer
/*
We're using the method `max` that exists on all `Int` values rather than an explicit `if` expression.
Note how similar the implementation is to `size`. We'll abstract out the common pattern in a later exercise.
*/
def maximum(t: Tree[Int]): Int = t match {
case Leaf(n) => n
case Branch(l,r) => maximum(l) max maximum(r)
}

Exercise 3.27
my impl
def depth[A](r: Tree[A]): Int = r match {
case Leaf(_) => 1
case Branch(l, r) => 1 + depth(l).max(depth(r))
}
answer
/*
Again, note how similar the implementation is to `size` and `maximum`.
*/
def depth[A](t: Tree[A]): Int = t match {
case Leaf(_) => 0
case Branch(l,r) => 1 + (depth(l) max depth(r))
}
パスの定義として、leafの時は0を返すべきだった

Exercise 3.28
my impl
def map[A,B](t: Tree[A])(f: A => B): Tree[B] = t match {
case Leaf(v) => Leaf(f(v))
case Branch(l, r) => Branch(map(l)(f), map(r)(f))
}
answer
def map[A,B](t: Tree[A])(f: A => B): Tree[B] = t match {
case Leaf(a) => Leaf(f(a))
case Branch(l,r) => Branch(map(l)(f), map(r)(f))
}
mapの実装は問題ないがテストの書き方。
"map" should "mapping function on each node" in {
val leaf1 = Leaf(1)
val leaf2 = Leaf(2)
val root = Branch(leaf1,leaf2)
val mappedTree = map(root)(a => a + a)
mappedTree match {
case Branch(l, r) => (l, r) match {
case (Leaf(lv), Leaf(rv)) => {
lv shouldEqual 2
rv shouldEqual 4
}
case _ => throw new Exception()
}
case _ => throw new Exception()
}
}
変数のパターンマッチ自体でassertすることはshould matchPattern {}
などでかないそうだが、マッチした変数を使ってさらにassertする場合のベストプラクティスがわからず。
普通に例外を投げてしまったがやり方としてどうなのか。

Exercise 3.29
my impl
def fold[A,B](t: Tree[A], acc: B)(f: (B, A) => B): B = t match {
case Leaf(v) => f(acc, v)
case Branch(l, r) => fold(r, fold(l, acc)(f))
}
answer
/*
Like `foldRight` for lists, `fold` receives a "handler" for each of the data constructors of the type, and recursively accumulates some value using these handlers. As with `foldRight`, `fold(t)(Leaf(_))(Branch(_,_)) == t`, and we can use this function to implement just about any recursive function that would otherwise be defined by pattern matching.
*/
def fold[A,B](t: Tree[A])(f: A => B)(g: (B,B) => B): B = t match {
case Leaf(a) => f(a)
case Branch(l,r) => g(fold(l)(f)(g), fold(r)(f)(g))
}
def sizeViaFold[A](t: Tree[A]): Int =
fold(t)(a => 1)(1 + _ + _)
def maximumViaFold(t: Tree[Int]): Int =
fold(t)(a => a)(_ max _)
def depthViaFold[A](t: Tree[A]): Int =
fold(t)(a => 0)((d1,d2) => 1 + (d1 max d2))
/*
Note the type annotation required on the expression `Leaf(f(a))`. Without this annotation, we get an error like this:
type mismatch;
found : fpinscala.datastructures.Branch[B]
required: fpinscala.datastructures.Leaf[B]
fold(t)(a => Leaf(f(a)))(Branch(_,_))
^
This error is an unfortunate consequence of Scala using subtyping to encode algebraic data types. Without the annotation, the result type of the fold gets inferred as `Leaf[B]` and it is then expected that the second argument to `fold` will return `Leaf[B]`, which it doesn't (it returns `Branch[B]`). Really, we'd prefer Scala to infer `Tree[B]` as the result type in both cases. When working with algebraic data types in Scala, it's somewhat common to define helper functions that simply call the corresponding data constructors but give the less specific result type:
def leaf[A](a: A): Tree[A] = Leaf(a)
def branch[A](l: Tree[A], r: Tree[A]): Tree[A] = Branch(l, r)
*/
def mapViaFold[A,B](t: Tree[A])(f: A => B): Tree[B] =
fold(t)(a => Leaf(f(a)): Tree[B])(Branch(_,_))
色々と間違っていた。
foldは3つの引数を取り、Leafのvalueを変換するf: A => B
と左右子の値をマージするg: (B, B) => B
を用意して、foldRightのように一度全て展開するような再帰的に実行される。

4 例外を使わないエラー処理
1章 p11
どのようなプログラムにおいても、プログラムの意味を変えることなく、式をその結果に置き換えることができる ー これが参照透過性です。また、参照透過な引数による呼び出しが参照透過になる関数を、純粋関数と呼びます。
例外によって参照透過性が損なわれるとは?
def failingFn(i: Int): Int = {
val y: Int = throw new Exception("fail!")
try {
val x = 42 + 5
x + y
}
catch { case e: Exception => 43 }
}
この関数を普通に実行すると、例外が投げられる。ここで、変数yの記述を削除しthrow new Exception("fail!")
そのままに置き換えると、
def failingFn(i: Int): Int = {
try {
val x = 42 + 5
x + ((throw new Exception("fail!"): Int)
}
catch { case e: Exception => 43 }
}
例外がキャッチされ、43が返されることになる。つまり、yを置き換えるとプログラムの挙動が変わる、つまり、yは参照透過ではないということになる。
つまり、その例外が投げられる外側のtryブロックの有無、挙動によって、プログラム全体の挙動が変わってしまう。≒コンテキストによって式の意味が変わる≒例外が参照透過を破壊している

Exercise 4.1
Optionの基本的なメソッドの実装、
mapとgetOrElseを除く関数はすべてパターンマッチングに頼らなくても実装できるはずである。
の制約に則って
my impl
sealed trait Option[+A] {
def map[B](f: A => B): Option[B] = this match {
case None => None
case Some(a) => Some(f(a))
}
def flatMap[B](f: A => Option[B]): Option[B] = map(f).getOrElse(None: Option[B])
def getOrElse[B >: A](default: => B): B = this match {
case None => default
case Some(a) => a
}
def orElse[B >: A](ob: => Option[B]): Option[B] = map(Some(_)).getOrElse(ob)
def filter(f: A => Boolean): Option[A] = flatMap(a => if (f(a)) Some(a) else None)
}
answer
def map[B](f: A => B): Option[B] = this match {
case None => None
case Some(a) => Some(f(a))
}
def getOrElse[B>:A](default: => B): B = this match {
case None => default
case Some(a) => a
}
def flatMap[B](f: A => Option[B]): Option[B] =
map(f) getOrElse None
/*
Of course, we can also implement `flatMap` with explicit pattern matching.
*/
def flatMap_1[B](f: A => Option[B]): Option[B] = this match {
case None => None
case Some(a) => f(a)
}
def orElse[B>:A](ob: => Option[B]): Option[B] =
this map (Some(_)) getOrElse ob
/*
Again, we can implement this with explicit pattern matching.
*/
def orElse_1[B>:A](ob: => Option[B]): Option[B] = this match {
case None => ob
case _ => this
}
/*
This can also be defined in terms of `flatMap`.
*/
def filter_1(f: A => Boolean): Option[A] =
flatMap(a => if (f(a)) Some(a) else None)
/* Or via explicit pattern matching. */
def filter(f: A => Boolean): Option[A] = this match {
case Some(a) if f(a) => this
case _ => None
}

Exercise 4.2
my impl
def variance(xs: Seq[Double]): Option[Double] = Some(xs).flatMap(s =>
if (d.isEmpty) None
else {
val m = s.sum / s.length
s.foldLeft(0)((acc, x) => acc + scala.math.pow(x - m, 2)) / s.length
}
)
コンパイルエラー
answer
def variance(xs: Seq[Double]): Option[Double] =
mean(xs) flatMap (m => mean(xs.map(x => math.pow(x - m, 2))))
flatMapをベースとして解けの意味がよくわからなかったが、式を見る限り返り値がOptionになる関数mean
を使って、ということのよう

Exercise 4.3
my impl
def map2[A,B,C](a: Option[A], b: Option[B])(f: (A, B) => C): Option[C] =
a.flatMap(av => b.map(bv => f(av, bv)))
answer
// a bit later in the chapter we'll learn nicer syntax for
// writing functions like this
def map2[A,B,C](a: Option[A], b: Option[B])(f: (A, B) => C): Option[C] =
a flatMap (aa => b map (bb => f(aa, bb)))

Exercise 4.4
my impl
def sequence[A](a: List[Option[A]]): Option[List[A]] =
a.foldRight(Some(List[A]()): Option[List[A]])((aa, b) => b.flatMap(bb => aa.map(aaa => aaa +: bb)))
answer
/*
Here's an explicit recursive version:
*/
def sequence[A](a: List[Option[A]]): Option[List[A]] =
a match {
case Nil => Some(Nil)
case h :: t => h flatMap (hh => sequence(t) map (hh :: _))
}
/*
It can also be implemented using `foldRight` and `map2`. The type annotation on `foldRight` is needed here; otherwise Scala wrongly infers the result type of the fold as `Some[Nil.type]` and reports a type error (try it!). This is an unfortunate consequence of Scala using subtyping to encode algebraic data types.
*/
def sequence_1[A](a: List[Option[A]]): Option[List[A]] =
a.foldRight[Option[List[A]]](Some(Nil))((x,y) => map2(x,y)(_ :: _))
せっかくさっき作ったmap2を使わずflatMapとmapをネストしてしまっているが、2つめの実装とほぼ同じ
Some(List[A]()): Option[List[A]]
のアノテーションを最初忘れてコンパイルエラーになった。

Exercise 4.5
my impl
def traverse[A,B](a: List[A])(f: A => Option[B]): Option[List[B]] =
a.foldRight(Some(Nil))((aa, b) => map2(f(aa), b)(_ :: _))
answer
def traverse[A, B](a: List[A])(f: A => Option[B]): Option[List[B]] =
a match {
case Nil => Some(Nil)
case h::t => map2(f(h), traverse(t)(f))(_ :: _)
}
def traverse_1[A, B](a: List[A])(f: A => Option[B]): Option[List[B]] =
a.foldRight[Option[List[B]]](Some(Nil))((h,t) => map2(f(h),t)(_ :: _))
def sequenceViaTraverse[A](a: List[Option[A]]): Option[List[A]] =
traverse(a)(x => x)
sequenceの結合部分でf: A => Option[B]
を適用する一手間を加えた感じ

for内包表記
def map2[A,B,C](a: Option[A], b: Option[B])(f: (A, B) => C): Option[C] =
for {
aa <- a
bb <- b
} yield f(aa, bb)
map2をfor内包表記を使って書くとこんな感じ

Either データ型
ここからEither
型に入っていく
定義
sealed trait Either[+E, +A]
case class Left[+E](value: E) extends Either[E, Nothing]
case Right[+A](value) extends Either[Nothing, A]
ちょくちょく出てくるNothingについて
scala.NothingはScalaのクラス階層における、「一番下」に位置するクラスで全ての型のサブタイプになるが
Nothingは全ての型のサブタイプであるため、どんな型の値にでも化けられるという性質がある。throw式の型をNothingとすれば、どんな型が要求されている箇所にthrow式が現れても適切に型付けされる。
全ての型のサブタイプであるNothing
は、Listや上記Eitherなどの共変の型パラメータが与えられるデータ型において、どんな型にでも化けられる便利な型としてデータ構造の定義時に使われる?
もう少し理解の深化が必要そう

p75
大まかに言えば、Eitherデータ型は2つのうちどちらかになる値を表します。つまり、2つの型の直和(非交和)であると言えます。
直和は数学の話、排他的論理和は論理の話らしい

Exercise 4.6
my impl
sealed trait Either[+E, +A] {
def map[B](f: A => B): Either[E, B] = this match {
case Left(value) => Left(value)
case Right(value) => Right(f(value))
}
def flatMap[EE >: E, B](f: A => Either[EE, B]): Either[EE, B] = this match {
case Left(e) => Left(e)
case Right(a) => f(a)
}
def orElse[EE >: E, B >: A](b: => Either[EE, B]): Either[EE, B] = this match {
case Left(_) => b
case Right(a) => Right(a)
}
def map2[EE >: E, B, C](b: Either[EE, B])(f: (A, B) => C): Either[EE, C] =
flatMap(a => b.map(bb => f(a, b)))
}
answer
def map[B](f: A => B): Either[E, B] =
this match {
case Right(a) => Right(f(a))
case Left(e) => Left(e)
}
def flatMap[EE >: E, B](f: A => Either[EE, B]): Either[EE, B] =
this match {
case Left(e) => Left(e)
case Right(a) => f(a)
}
def orElse[EE >: E, AA >: A](b: => Either[EE, AA]): Either[EE, AA] =
this match {
case Left(_) => b
case Right(a) => Right(a)
}
def map2[EE >: E, B, C](b: Either[EE, B])(f: (A, B) => C):
Either[EE, C] = for { a <- this; b1 <- b } yield f(a,b1)

Exercise 4.7
my impl
def sequence[E, A](es: List[Either[E, A]]): Either[E, List[A]] =
es.foldRight(Right(List[A]()): Either[E, List[A]])((a, b) => a.map2(b)((aa, bb) => aa +: bb))
def traverse[E, A, B](as: List[A])(f: A => Either[E, B]): Either[E, List[B]] =
as.foldRight(Right(List[B]()): Either[E, List[A]])((a, b) => f(a).map2(b)(_ :: _))
answer
def traverse[E,A,B](es: List[A])(f: A => Either[E, B]): Either[E, List[B]] =
es match {
case Nil => Right(Nil)
case h::t => (f(h) map2 traverse(t)(f))(_ :: _)
}
def traverse_1[E,A,B](es: List[A])(f: A => Either[E, B]): Either[E, List[B]] =
es.foldRight[Either[E,List[B]]](Right(Nil))((a, b) => f(a).map2(b)(_ :: _))
def sequence[E,A](es: List[Either[E,A]]): Either[E,List[A]] =
traverse(es)(x => x)
traverseを使ってsequenceを実装する方が記述がシンプルになる。
型パラメータの与え方、空のListはNil
を使えば勝手に化けてくれる

Exercise 4.8
エラーを蓄積するためのデータ構造
answer
/*
There are a number of variations on `Option` and `Either`. If we want to accumulate multiple errors, a simple approach is a new data type that lets us keep a list of errors in the data constructor that represents failures:
trait Partial[+A,+B]
case class Errors[+A](get: Seq[A]) extends Partial[A,Nothing]
case class Success[+B](get: B) extends Partial[Nothing,B]
There is a type very similar to this called `Validation` in the Scalaz library. You can implement `map`, `map2`, `sequence`, and so on for this type in such a way that errors are accumulated when possible (`flatMap` is unable to accumulate errors--can you see why?). This idea can even be generalized further--we don't need to accumulate failing values into a list; we can accumulate values using any user-supplied binary function.
It's also possible to use `Either[List[E],_]` directly to accumulate errors, using different implementations of helper functions like `map2` and `sequence`.
*/

5 正格と遅延
例えば、Listにmapとfilter処理をするとき、まとめて処理を行うことができれば1回のループで済ませることができる。
p80
こうしたループの自動的な融合は、非正格性(non-strictness)を使って実現できます。非正格性については、遅延性(laziness)と言ったほうがピンとくるかもしれません。
短絡論理関数&&
および||
は、非正格の例
必要ない場合は、2つ目の引数を評価しない
また、scalaのif
式もそう

非正格関数であるifの実装
def if2[A](cond: Boolean, onTrue: () => A, onFalse: () => A): A =
if (cond) onTrue() else onFalse()
$ if (a > 22,
() => println("a"),
() => println("b")
)
評価せずに渡したい引数の手前に() =>
がついている。評価されない式を一般にサンク(thunk)と呼び、サンクに対してはonTrue()
やonFalse()
のように関数を呼び出して空の引数リストを渡すことで、式の評価と結果の取得を強制することができる。
これは非常によくあるケースなため、より便利な構文が用意されている。
def if2[A](cond: Boolean, onTrue: => A, onFalse: => A): A =
if (cond) onTrue else onFalse
これは上の例と同じ挙動の関数になっている。
このように評価されずに関数に渡される引数は、関数の本体内で参照されるたびに1回評価される(引数の評価結果がキャッシュされない)
このような値を明示的にキャッシュするためにlazy
キーワードがあり、
def maybeTwice(b: Boolean, i: => Int) = {
lazy val j = i
if (b) j+j else 0
}
のようにval宣言にlazyキーワードを追加した変数に代入することで、宣言の右辺の評価が最初に参照される時まで先送りする性質を保ちつつ、その後の参照で評価が繰り返されないよう結果をキャッシュすることができる。

p83
なお、Scalaの非正格関数は引数を値渡しではなく名前渡しで受け取ります。

遅延リストの定義
trait Stream[+A]
case object Empty extends Stream[Nothing]
case class Cons[+A](h: () => A, t: () => Stream[A]) extends Stream[A]
object Stream {
def cons[A](hd: => A, tl: => Stream[A]): Stream[A] = {
lazy val head = hd
lazy val tail = tl
Cons(() => head, () => tail)
}
def empty[A]: Stream[A] = Empty
def apply[A](as: A*): Stream[A] =
if (as.isEmpty) empty
else cons(as.head, apply(as.tail: _*))
}
List型とよく似ているが、Consデータコンストラクタは正格値ではなく明示的なサンクを受け取る。そのため、Streamを調査または走査するには、サンクを強制的に評価する必要がある。
その例
trait Stream[+A] {
def headOption: Option[A] = this match {
case Empty => None
case Cons(h, t) => Some(h())
}
}
h()
が強制的に評価している部分

Consデータコンストラクタを直接呼び出した場合、以下のコードはexpensive(x)
を実際には2回計算してしまう。
val x = Cons(() => expensive(x), tl)
val h1 = x.headOption
val h2 = x.headOption
一般的には、スマートコンストラクタを定義することでこの問題を回避する。
def cons[A](hd: => A, tl: => Stream[A]): Stream[A] = {
lazy val head = hd
lazy val tail = tl
Cons(() => head, () => tail)
}
サンクの処理が実行されるのは強制的な評価が最初に行われた時だけとなり、それ以降はキャッシュされた遅延値が返される

Exercise 5.1
answer
// The natural recursive solution
def toListRecursive: List[A] = this match {
case Cons(h,t) => h() :: t().toListRecursive
case _ => List()
}
/*
The above solution will stack overflow for large streams, since it's
not tail-recursive. Here is a tail-recursive implementation. At each
step we cons onto the front of the `acc` list, which will result in the
reverse of the stream. Then at the end we reverse the result to get the
correct order again.
[:ben] are the line breaks above okay? I'm unclear on whether these "hints" are supposed to go in the book or not
*/
def toList: List[A] = {
@annotation.tailrec
def go(s: Stream[A], acc: List[A]): List[A] = s match {
case Cons(h,t) => go(t(), h() :: acc)
case _ => acc
}
go(this, List()).reverse
}
/*
In order to avoid the `reverse` at the end, we could write it using a
mutable list buffer and an explicit loop instead. Note that the mutable
list buffer never escapes our `toList` method, so this function is
still _pure_.
*/
def toListFast: List[A] = {
val buf = new collection.mutable.ListBuffer[A]
@annotation.tailrec
def go(s: Stream[A]): List[A] = s match {
case Cons(h,t) =>
buf += h()
go(t())
case _ => buf.toList
}
go(this)
}

Exercise 5.2
my impl
def take(n: Int): List[A] = this match {
case Cons(h, t) if (n <= 1) => List(h())
case Cons(h, t) => h() :: t().take(n - 1)
case _ => List()
}
def drop(n: Int): Stream[A] = this match {
case Cons(h, t) if (n < 1) => this
case Cons(h, t) => t().drop(n - 1)
case _ => Empty
}
answer
/*
`take` first checks if n==0. In that case we need not look at the stream at all.
*/
def take(n: Int): Stream[A] = this match {
case Cons(h, t) if n > 1 => cons(h(), t().take(n - 1))
case Cons(h, _) if n == 1 => cons(h(), empty)
case _ => empty
}
/*
Unlike `take`, `drop` is not incremental. That is, it doesn't generate the
answer lazily. It must traverse the first `n` elements of the stream eagerly.
*/
@annotation.tailrec
final def drop(n: Int): Stream[A] = this match {
case Cons(_, t) if n > 0 => t().drop(n - 1)
case _ => this
}
最初takeの実装時Listに戻り値をListにしてしまったが、その必要はなかったのでdropでは軌道修正。
値が評価されても、評価済みの値がキャッシュされたStreamデータ型として扱える、ということのはず

Exercise 5.3
my impl
def takeWhile(p: A => Boolean): Stream[A] = this match {
case Cons(h, t) if (p(h())) => cons(h(), t().takeWhile(p))
case _ => Empty
}
answer
/*
It's a common Scala style to write method calls without `.` notation, as in `t() takeWhile f`.
*/
def takeWhile(f: A => Boolean): Stream[A] = this match {
case Cons(h,t) if f(h()) => cons(h(), t() takeWhile f)
case _ => empty
}

Exercise 5.4
my impl
def forAll(p: A => Boolean): Boolean =
foldRight(true)((a, b) => b && p(a))
answer
/*
Since `&&` is non-strict in its second argument, this terminates the traversal as soon as a nonmatching element is found.
*/
def forAll(f: A => Boolean): Boolean =
foldRight(true)((a,b) => f(a) && b)
勘違いでbを先に評価しようとしてしまったが、f(a)を評価してfalseだった場合は走査を止めることで、bが評価されずチェックが終了する。
チェックがfalseに終わった以降右の要素が評価されない
挙動を試してみる。
テストを用意
package laziness
import org.scalatest._
import laziness.Stream._
import laziness.{Stream,Cons,Empty}
class StreamSpec extends FlatSpec with Matchers {
"forAll" should "forAll" in {
val s = Stream.apply(1,2,3,4,5)
s.forAll(n => n < 3) shouldEqual false
}
}
forAllの挙動を修正、bの評価の前にaを出力するようにしてみる。
def forAll(p: A => Boolean): Boolean =
foldRight(true)((a, b) => {
p(a) && {
println(a)
b
}
})
これでテストを実行すると、
$ [info] Compiling 1 Scala source to /workspace/target/scala-2.12/classes ...
$ [info] Done compiling.
$ 1
$ 2
やはりp(a)
がfalseになった以降はbが評価されていないのがわかる

Exercise 5.5
my impl
def takeWhileViaFoldRight(p: A => Boolean): Stream[A] =
foldRight(empty[A])((a, b) => if(p(a)) cons(a, b) else b)
answer
def takeWhile_1(f: A => Boolean): Stream[A] =
foldRight(empty[A])((h,t) =>
if (f(h)) cons(h,t)
else empty)

Exercise 5.6
my impl
def headOptionViaFoldRight: Option[A] =
foldRight(None: Option[A])((a, b) => Some(a))
answer
def headOption: Option[A] =
foldRight(None: Option[A])((h,_) => Some(h))

Exercise 5.7
my impl
def map[B](f: A => B): Stream[B] =
foldRight(empty: Stream[B])((h, t) => cons(f(h), t))
def filter(f: A => Boolean): Stream[A] =
foldRight(empty[A])((h, t) => if (f(h)) cons(h, t) else t)
def append[AA >: A](s: Stream[AA]): Stream[AA] =
foldRight(s)((h, t) => cons(h, t))
def flatMap[B](f: A => Stream[B]): Stream[B] =
foldRight(empty: Stream[B])((h, t) => f(h).append(t))
answer
def map[B](f: A => B): Stream[B] =
foldRight(empty[B])((h,t) => cons(f(h), t))
def filter(f: A => Boolean): Stream[A] =
foldRight(empty[A])((h,t) =>
if (f(h)) cons(h, t)
else t)
def append[B>:A](s: => Stream[B]): Stream[B] =
foldRight(s)((h,t) => cons(h,t))
def flatMap[B](f: A => Stream[B]): Stream[B] =
foldRight(empty[B])((h,t) => f(h) append t)
perfect、appendの時の型パラメータの与え方がポインt

Exercise 5.8
my impl
def constant[A](a: A): Stream[A] = cons(a, constant(a))
answer
// This is more efficient than `cons(a, constant(a))` since it's just
// one object referencing itself.
def constant[A](a: A): Stream[A] = {
lazy val tail: Stream[A] = Cons(() => a, () => tail)
tail
}

Exercise 5.9
my impl
def from(n: Int): Stream[Int] = cons(n, from(n + 1))
answer
def from(n: Int): Stream[Int] =
cons(n, from(n+1))

Exercise 5.10
my impl
def fibs(): Stream[Int] = {
def go(p1: Int, p2: Int): Stream[Int] = {
lazy val cur = p1 + p2
cons(cur, go(cur, p1))
}
cons(0, go(0, 1))
}
answer
val fibs = {
def go(f0: Int, f1: Int): Stream[Int] =
cons(f0, go(f1, f0+f1))
go(0, 1)
}

Exercise 5.11
my impl
def unfold[A, S](z: S)(f: S => Option[(A, S)]): Stream[A] =
f(z).map {
case (a, s) => cons(a, unfold(s)(f))
}.getOrElse(empty)
answer
def unfold[A, S](z: S)(f: S => Option[(A, S)]): Stream[A] =
f(z) match {
case Some((h,s)) => cons(h, unfold(s)(f))
case None => empty
}

Exercise 5.12
my impl
val fibsViaUnfold = {
unfold((0, 1)){
case (i1, i2) => Some((i1, (i2, i1 + i2)))
}
}
def fromViaUnfold(n: Int): Stream[Int] =
unfold(n)(s => Some((s, s + 1)))
def constantViaUnfold[A](a: A): Stream[A] =
unfold(a)(aa => Some(aa, aa))
val ones: Stream[Int] = unfold(1)(i => Some(1, 1))
answer
/*
Scala provides shorter syntax when the first action of a function literal is to match on an expression. The function passed to `unfold` in `fibsViaUnfold` is equivalent to `p => p match { case (f0,f1) => ... }`, but we avoid having to choose a name for `p`, only to pattern match on it.
*/
val fibsViaUnfold =
unfold((0,1)) { case (f0,f1) => Some((f0,(f1,f0+f1))) }
def fromViaUnfold(n: Int) =
unfold(n)(n => Some((n,n+1)))
def constantViaUnfold[A](a: A) =
unfold(a)(_ => Some((a,a)))
// could also of course be implemented as constant(1)
val onesViaUnfold = unfold(1)(_ => Some((1,1)))

Exercise 5.13
my impl
def mapViaUnfold[B](f: A => B): Stream[B] =
unfold(this)(s => s match {
case Cons(h, t) => Some((f(h()), t()))
case _ => None
})
def takeViaUnfold(n: Int): Stream[A] =
unfold(this) {
case Cons(h, t) if 0 < n => Some((h(), t().takeViaUnfold(n - 1)))
case _ => None
}
def takeWhileViaUnfold(f: A => Boolean): Stream[A] =
unfold(this) {
case Cons(h, t) if (f(h())) => Some((h(), t().takeWhileViaUnfold(f)))
case _ => None
}
def zipWith[B, C](s: Stream[B])(f: (A, B) => C): Stream[C] =
unfold((this, s)) {
case (Cons(h, t), Cons(hh, tt)) => Some((f(h(), hh()), (t(), tt())))
case _ => None
}
def zipAll[B](s2: Stream[B]): Stream[(Option[A], Option[B])] =
unfold((this, s2)) {
case (Cons(h, t), Cons(hh, tt)) => Some(((Some(h()), Some(hh())), (t(), tt())))
case (Cons(h, t), _) => Some(((Some(h()), None), (t(), empty)))
case (_, Cons(h, t)) => Some(((None, Some(h())), (empty, t())))
case _ => None
}
answer
def mapViaUnfold[B](f: A => B): Stream[B] =
unfold(this) {
case Cons(h,t) => Some((f(h()), t()))
case _ => None
}
def takeViaUnfold(n: Int): Stream[A] =
unfold((this,n)) {
case (Cons(h,t), 1) => Some((h(), (empty, 0)))
case (Cons(h,t), n) if n > 1 => Some((h(), (t(), n-1)))
case _ => None
}
def takeWhileViaUnfold(f: A => Boolean): Stream[A] =
unfold(this) {
case Cons(h,t) if f(h()) => Some((h(), t()))
case _ => None
}
def zipWith[B,C](s2: Stream[B])(f: (A,B) => C): Stream[C] =
unfold((this, s2)) {
case (Cons(h1,t1), Cons(h2,t2)) =>
Some((f(h1(), h2()), (t1(), t2())))
case _ => None
}
// special case of `zipWith`
def zip[B](s2: Stream[B]): Stream[(A,B)] =
zipWith(s2)((_,_))
def zipAll[B](s2: Stream[B]): Stream[(Option[A],Option[B])] =
zipWithAll(s2)((_,_))
def zipWithAll[B, C](s2: Stream[B])(f: (Option[A], Option[B]) => C): Stream[C] =
Stream.unfold((this, s2)) {
case (Empty, Empty) => None
case (Cons(h, t), Empty) => Some(f(Some(h()), Option.empty[B]) -> (t(), empty[B]))
case (Empty, Cons(h, t)) => Some(f(Option.empty[A], Some(h())) -> (empty[A] -> t()))
case (Cons(h1, t1), Cons(h2, t2)) => Some(f(Some(h1()), Some(h2())) -> (t1() -> t2()))
}
takeとtakeWhileが間違っている

def takeViaUnfold(n: Int): Stream[A] =
unfold(this) {
case Cons(h, t) if 0 < n => Some((h(), t().takeViaUnfold(n - 1)))
case _ => None
}
def takeViaUnfold(n: Int): Stream[A] =
unfold((this,n)) {
case (Cons(h,t), 1) => Some((h(), (empty, 0)))
case (Cons(h,t), n) if n > 1 => Some((h(), (t(), n-1)))
case _ => None
}

Exercise 5.14
my impl
def startsWith[A](s: Stream[A]): Boolean =
zipAll(s).forAll {
case (s1, s2) => (s1.nonEmpty && s2.isEmpty) || (s1.nonEmpty && s2.nonEmpty && s1.get == s2.get)
}
answer
/*
`s startsWith s2` when corresponding elements of `s` and `s2` are all equal, until the point that `s2` is exhausted. If `s` is exhausted first, or we find an element that doesn't match, we terminate early. Using non-strictness, we can compose these three separate logical steps--the zipping, the termination when the second stream is exhausted, and the termination if a nonmatching element is found or the first stream is exhausted.
*/
def startsWith[A](s: Stream[A]): Boolean =
zipAll(s).takeWhile(!_._2.isEmpty) forAll {
case (h,h2) => h == h2
}
勘所は掴んでいたが、.takeWhile(!_._2.isEmpty)
がポイント
zipAllとforAllだけの自分の実装だと全ての要素を走査してしまう。

Exercise 5.15
my impl
def tails: Stream[Stream[A]] =
unfold(this) {
case Cons(h, t) => Some(cons(h(), t()), t())
case _ => None
}
answer
/*
The last element of `tails` is always the empty `Stream`, so we handle this as a special case, by appending it to the output.
*/
def tails: Stream[Stream[A]] =
unfold(this) {
case Empty => None
case s => Some((s, s drop 1))
} append Stream(empty)
dropを使うことでStreamの要素を展開する必要がないのと、最後にStream(empty)
を追加する必要があった。

Exercise 5.16
my impl
def scanRight[B](z: => B)(f: (A, => B) => B): Stream[B] =
foldRight(cons(z, empty))((a, b) => cons(f(a, b.headOption.get), b))
unfold
は左から要素を生成していくので、右から畳み込むscanRightのような関数の実装には使えないのでは?
answer
/*
The function can't be implemented using `unfold`, since `unfold` generates elements of the `Stream` from left to right. It can be implemented using `foldRight` though.
The implementation is just a `foldRight` that keeps the accumulated value and the stream of intermediate results, which we `cons` onto during each iteration. When writing folds, it's common to have more state in the fold than is needed to compute the result. Here, we simply extract the accumulated list once finished.
*/
def scanRight[B](z: B)(f: (A, => B) => B): Stream[B] =
foldRight((z, Stream(z)))((a, p0) => {
// p0 is passed by-name and used in by-name args in f and cons. So use lazy val to ensure only one evaluation...
lazy val p1 = p0
val b2 = f(a, p1._1)
(b2, cons(b2, p1._2))
})._2
unfoldでは実装できない、という結論は正しい。
自分の実装だとおそらく
scanRight関数では、中間結果を再利用することで、n個の要素を持つStreamの評価にかかる時間が常にnに対して線形になるようにすべきである。
の条件を満たせていない?
右から畳み込んでいく中で一つ前の要素(一つ右の要素)を参照する時にキャッシュされておらず、評価が再度走ってしまう、ということか

5 純粋関数型の状態

Exercise 6.1
answer
def nonNegativeInt(rng: RNG): (Int, RNG) = {
val (i, r) = rng.nextInt
(if (i < 0) -(i + 1) else i, r)
}
0以上Int.MaxValue以下の数字と、0未満Int.MinValue以上の数字の個数は同じなので、上のように1つずらして符号を変えれば良いだけだった。

Exercise 6.2
my impl
def double(rng: RNG): (Double, RNG) = {
val (i, r) = rng.nextInt
val a / (b + c)
(if (i < 0) (i + 1).toDouble / Int.MinValue else -(i.toDouble / Int.MinValue), r)
}
answer
// We generate an integer >= 0 and divide it by one higher than the
// maximum. This is just one possible solution.
def double(rng: RNG): (Double, RNG) = {
val (i, r) = nonNegativeInt(rng)
(i / (Int.MaxValue.toDouble + 1), r)
}
Intの範囲だとMaxValueよりMinValueの方が絶対値が1大きいのでそれを利用しようとしたが、そもそも前のnonNegativeInt
を利用した上で、割る数を先にDoubleに変換すればInt.MaxValueの1上の範囲の値にできるので、それによって0~1(1を含まない)値を生成できる。

Exercise 6.3
my impl
def intDouble(rng: RNG): ((Int, Double), RNG) = {
val (i, r) = nonNegativeInt(rng)
val (d, r2) = double(r)
((i, d), r2)
}
def doubleInt(rng: RNG): ((Double, Int), RNG) = {
val (d, r) = double(rng)
val (i, r2) = nonNegativeInt(r)
((d, i), r2)
}
def double3(rng: RNG): ((Double, Double, Double), RNG) = {
val (d, r) = double(rng)
val (d2, r2) = double(r)
val (d3, r3) = double(r2)
((d, d2, d3), r3)
}
answer
def intDouble(rng: RNG): ((Int, Double), RNG) = {
val (i, r1) = rng.nextInt
val (d, r2) = double(r1)
((i, d), r2)
}
def doubleInt(rng: RNG): ((Double, Int), RNG) = {
val ((i, d), r) = intDouble(rng)
((d, i), r)
}
def double3(rng: RNG): ((Double, Double, Double), RNG) = {
val (d1, r1) = double(rng)
val (d2, r2) = double(r1)
val (d3, r3) = double(r2)
((d1, d2, d3), r3)
}
// There is something terribly repetitive about passing the RNG along
// every time. What could we do to eliminate some of this duplication
// of effort?

Exercise 6.4
my impl
def ints(count: Int)(rng: RNG): (List[Int], RNG) = {
if (count < 1) return (Nil, rng)
else {
val (i, r) = nonNegativeInt(rng)
val (tails, r2) = ints(count - 1)(r)
(i +: tails, r2)
}
}
answer
// A simple recursive solution
def ints(count: Int)(rng: RNG): (List[Int], RNG) =
if (count <= 0)
(List(), rng)
else {
val (x, r1) = rng.nextInt
val (xs, r2) = ints(count - 1)(r1)
(x :: xs, r2)
}
// A tail-recursive solution
def ints2(count: Int)(rng: RNG): (List[Int], RNG) = {
def go(count: Int, r: RNG, xs: List[Int]): (List[Int], RNG) =
if (count <= 0)
(xs, r)
else {
val (x, r2) = r.nextInt
go(count - 1, r2, x :: xs)
}
go(count, rng, List())
}
ほぼ合っているが、nonNegativeInt()
を使う必要はなかった

ある型Aに対してRNG => (A, RNG)形式の型が使用されている、この種の関数はRNGの状態を遷移させることから状態アクションまたは状態遷移と呼ばれる。
状態データ型であるRNGの型エイリアスを作成する
type Rand[+A] = RNG => (A, RNG)

Exercise 6.5
my impl
def doubleViaMap: Rand[Double] =
map(nonNegativeInt)(i => i / (Int.MaxValue.toDouble + 1))
answer
val _double: Rand[Double] =
map(nonNegativeInt)(_ / (Int.MaxValue.toDouble + 1))

Exercise 6.6
my impl
def map2[A,B,C](ra: Rand[A], rb: Rand[B])(f: (A, B) => C): Rand[C] =
rng => {
val (a, rng2) = ra(rng)
val (b, rng3) = rb(rng2)
(f(a, b), rng3)
}
answer
// This implementation of map2 passes the initial RNG to the first argument
// and the resulting RNG to the second argument. It's not necessarily wrong
// to do this the other way around, since the results are random anyway.
// We could even pass the initial RNG to both `f` and `g`, but that might
// have unexpected results. E.g. if both arguments are `RNG.int` then we would
// always get two of the same `Int` in the result. When implementing functions
// like this, it's important to consider how we would test them for
// correctness.
def map2[A,B,C](ra: Rand[A], rb: Rand[B])(f: (A, B) => C): Rand[C] =
rng => {
val (a, r1) = ra(rng)
val (b, r2) = rb(r1)
(f(a, b), r2)
}

Exercise 6.7
my impl
def sequence[A](fs: List[Rand[A]]): Rand[List[A]] =
fs.foldRight(rng => {
val (i, r2) = rng.nextInt
(List(), r2)
})((ra, b: Rand[List[A]]) => map2(ra, b)(_ :: _))
answer
// In `sequence`, the base case of the fold is a `unit` action that returns
// the empty list. At each step in the fold, we accumulate in `acc`
// and `f` is the current element in the list.
// `map2(f, acc)(_ :: _)` results in a value of type `Rand[List[A]]`
// We map over that to prepend (cons) the element onto the accumulated list.
//
// We are using `foldRight`. If we used `foldLeft` then the values in the
// resulting list would appear in reverse order. It would be arguably better
// to use `foldLeft` followed by `reverse`. What do you think?
def sequence[A](fs: List[Rand[A]]): Rand[List[A]] =
fs.foldRight(unit(List[A]()))((f, acc) => map2(f, acc)(_ :: _))
// It's interesting that we never actually need to talk about the `RNG` value
// in `sequence`. This is a strong hint that we could make this function
// polymorphic in that type.
def _ints(count: Int): Rand[List[Int]] =
sequence(List.fill(count)(int))
unit()
の意味と使い方を理解。
方針としては間違っていない

Exercise 6.8
my impl
def flatMap[A,B](f: Rand[A])(g: A => Rand[B]): Rand[B] =
rng => {
val (a, rng2) = f(rng)
g(a)(rng2)
}
def nonNegativeLessThan(n: Int): Rand[Int] =
flatMap(nonNegativeInt) { i =>
val mod = i % n
if (i + (n - 1) - mod >= 0) unit(mod) else nonNegativeLessThan(n)
}
answer
def flatMap[A,B](f: Rand[A])(g: A => Rand[B]): Rand[B] =
rng => {
val (a, r1) = f(rng)
g(a)(r1) // We pass the new state along
}
def nonNegativeLessThan(n: Int): Rand[Int] = {
flatMap(nonNegativeInt) { i =>
val mod = i % n
if (i + (n-1) - mod >= 0) unit(mod) else nonNegativeLessThan(n)
}
}

Exercise 6.9
my impl
def mapViaFlatMap[A,B](s: Rand[A])(f: A => B): Rand[B] =
flatMap(s)(a => unit(f(a)))
def map2ViaFlatMap[A,B,C](ra: Rand[A], rb: Rand[B])(f: (A, B) => C): Rand[C] =
flatMap(ra) { a =>
map(rb)(b => f(a, b))
}
answer
def _map[A,B](s: Rand[A])(f: A => B): Rand[B] =
flatMap(s)(a => unit(f(a)))
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)))

Exercise 6.10
my impl
case class State[S,+A](run: S => (A,S)) {
def map[B](f: A => B): State[S, B] =
s => {
val (a, s2) = run(s)
(f(a), s2)
}
def map2[B,C](run2: S => (B,S))(f: (A, B) => C): State[S, C] =
s => {
val (a, s2) = run(s)
val (b, s3) = run2(s2)
(f(a, b), s3)
}
def flatMap[B](f: A => State[S, B]): State[S, B] =
s => {
val (a, s2) = run(s)
f(a)(s2)
}
}
object State {
type Rand[A] = State[RNG, A]
def unit[S,A](a: A): State[S, A] = s => (a, s)
def sequence[S,A](fs: List[State[S, A]]): State[S, List[A]] =
fs.foldRight(unit(List()))((a, acc) => a.map2(acc)(_ :: _))
}
answer
case class State[S, +A](run: S => (A, S)) {
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)))
def flatMap[B](f: A => State[S, B]): State[S, B] = State(s => {
val (a, s1) = run(s)
f(a).run(s1)
})
}
object State {
def unit[S, A](a: A): State[S, A] =
State(s => (a, s))
// The idiomatic solution is expressed via foldRight
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)(_ :: _))
// This implementation uses a loop internally and is the same recursion
// pattern as a left fold. It is quite common with left folds to build
// up a list in reverse order, then reverse it at the end.
// (We could also use a collection.mutable.ListBuffer internally.)
def sequence[S, A](sas: List[State[S, A]]): State[S, List[A]] = {
def go(s: S, actions: List[State[S,A]], acc: List[A]): (List[A],S) =
actions match {
case Nil => (acc.reverse,s)
case h :: t => h.run(s) match { case (a,s2) => go(s2, t, a :: acc) }
}
State((s: S) => go(s,sas,List()))
}
// We can also write the loop using a left fold. This is tail recursive like the
// previous solution, but it reverses the list _before_ folding it instead of after.
// You might think that this is slower than the `foldRight` solution since it
// walks over the list twice, but it's actually faster! The `foldRight` solution
// technically has to also walk the list twice, since it has to unravel the call
// stack, not being tail recursive. And the call stack will be as tall as the list
// is long.
def sequenceViaFoldLeft[S,A](l: List[State[S, A]]): State[S, List[A]] =
l.reverse.foldLeft(unit[S, List[A]](List()))((acc, f) => f.map2(acc)( _ :: _ ))
def modify[S](f: S => S): State[S, Unit] = for {
s <- get // Gets the current state and assigns it to `s`.
_ <- set(f(s)) // Sets the new state to `f` applied to `s`.
} yield ()
def get[S]: State[S, S] = State(s => (s, s))
def set[S](s: S): State[S, Unit] = State(_ => ((), s))
}
RNGはその型エイリアス自体が状態アクションを示していたが、State case classではrun()
がアクションを示すため、書き方が変わっている部分がある、

2章は並列化のモジュールに関する項
スレッドの概念など基礎を入れるために
増補改訂版 Java言語で学ぶデザインパターン入門 マルチスレッド編
を通読した後こちらに戻る

5 純粋関数型の並列処理
Exercise 7.1
answer
def map2[A,B,c](a: Par[A], b: Par[B])(f: (A, B) => C): Par[C]

p124
map2の正格性を保ちつつ、実行をすぐに開始させないとしたらどうでしょうか。
~
p125
この記述の格納にどのようなデータ構造を使用したとしても、元のリストよりも多くのスペースを占めることになるでしょう。記述がもう少し単純であればよかったのですが。
map2を先送りし、両半分の計算をすぐに同時に開始したほうが良さそうです。そうすれば、どちらかが優先されるという問題も解決です。

Exercise 7.3
answer
/* This version respects timeouts. See `Map2Future` below. */
def map2[A,B,C](a: Par[A], b: Par[B])(f: (A,B) => C): Par[C] =
es => {
val (af, bf) = (a(es), b(es))
Map2Future(af, bf, f)
}
/*
Note: this implementation will not prevent repeated evaluation if multiple threads call `get` in parallel. We could prevent this using synchronization, but it isn't needed for our purposes here (also, repeated evaluation of pure values won't affect results).
*/
case class Map2Future[A,B,C](a: Future[A], b: Future[B],
f: (A,B) => C) extends Future[C] {
@volatile var cache: Option[C] = None
def isDone = cache.isDefined
def isCancelled = a.isCancelled || b.isCancelled
def cancel(evenIfRunning: Boolean) =
a.cancel(evenIfRunning) || b.cancel(evenIfRunning)
def get = compute(Long.MaxValue)
def get(timeout: Long, units: TimeUnit): C =
compute(TimeUnit.NANOSECONDS.convert(timeout, units))
private def compute(timeoutInNanos: Long): C = cache match {
case Some(c) => c
case None =>
val start = System.nanoTime
val ar = a.get(timeoutInNanos, TimeUnit.NANOSECONDS)
val stop = System.nanoTime;val aTime = stop-start
val br = b.get(timeoutInNanos - aTime, TimeUnit.NANOSECONDS)
val ret = f(ar, br)
cache = Some(ret)
ret
}
}

Exercise 7.4
my impl
def asyncF[A,B](f: A => B): A => Par[B] = (a: A) => lazyUnit(f(a))
answer
def asyncF[A,B](f: A => B): A => Par[B] =
a => lazyUnit(f(a))

Exercise 7.5
my impl
def sequence[A](ps: List[Par[A]]): Par[List[A]] = {
ps.foldRight(unit(()))((a, b) => map2(b, a))
}
answer
def sequence_simple[A](l: List[Par[A]]): Par[List[A]] =
l.foldRight[Par[List[A]]](unit(List()))((h,t) => map2(h,t)(_ :: _))
// This implementation forks the recursive step off to a new logical thread,
// making it effectively tail-recursive. However, we are constructing
// a right-nested parallel program, and we can get better performance by
// dividing the list in half, and running both halves in parallel.
// See `sequenceBalanced` below.
def sequenceRight[A](as: List[Par[A]]): Par[List[A]] =
as match {
case Nil => unit(Nil)
case h :: t => map2(h, fork(sequenceRight(t)))(_ :: _)
}
// We define `sequenceBalanced` using `IndexedSeq`, which provides an
// efficient function for splitting the sequence in half.
def sequenceBalanced[A](as: IndexedSeq[Par[A]]): Par[IndexedSeq[A]] = fork {
if (as.isEmpty) unit(Vector())
else if (as.length == 1) map(as.head)(a => Vector(a))
else {
val (l,r) = as.splitAt(as.length/2)
map2(sequenceBalanced(l), sequenceBalanced(r))(_ ++ _)
}
}
def sequence[A](as: List[Par[A]]): Par[List[A]] =
map(sequenceBalanced(as.toIndexedSeq))(_.toList)
そもそもmap2の引数はカリー化された2つのグループが必要だった。

Exercise 7.6
answer
def parFilter[A](l: List[A])(f: A => Boolean): Par[List[A]] = {
val pars: List[Par[List[A]]] =
l map (asyncF((a: A) => if (f(a)) List(a) else List()))
map(sequence(pars))(_.flatten) // convenience method on `List` for concatenating a list of lists
}

Exercise 7.11
my impl
def choiceN[A](n: Par[Int])(choices: List[Par[A]]): Par[A] =
es => choices(run(es)(n).get)(es)
def choice[A](cond: Par[Boolean])(t: Par[A], f: Par[A]): Par[A] =
choiceN(map(cond)(b => if (b) 0 else 1))(List(t, f))
answer
def choiceN[A](n: Par[Int])(choices: List[Par[A]]): Par[A] =
es => {
val ind = run(es)(n).get // Full source files
run(es)(choices(ind))
}
def choiceViaChoiceN[A](a: Par[Boolean])(ifTrue: Par[A], ifFalse: Par[A]): Par[A] =
choiceN(map(a)(b => if (b) 0 else 1))(List(ifTrue, ifFalse))
自分のchoiceNではchoicesから選ばれたParにesを渡して直接実行しているが、これはrunで行われている操作と一緒。runが用意されているのでそちらを使用するべきだった。
これらはFutureのgetを呼び出しており、ブロッキング

Exercise 7.12
my impl
def choiceMap[K, V](key: Par[K])(choices: Map[K, Par[V]]): Par[V] =
es => {
val k = run(es)(key).get
run(es)(choices(k))
}
answer
def choiceMap[K,V](key: Par[K])(choices: Map[K,Par[V]]): Par[V] =
es => {
val k = run(es)(key).get
run(es)(choices(k))
}
choiceNを少し修正しただけ

Exercise 7.13
my impl
def chooser[A, B](pa: Par[A])(choices: A => Par[B]): Par[B] =
es => {
val s = run(es)(pa).get
run(es)(choices(s))
}
def choiceViaChooser[A](cond: Par[Boolean])(t: Par[A], f: Par[A]): Par[A] =
chooser(cond)(b => if (b) t else f)
def choiceNViaChooser[A](n: Par[Int])(choices: List[Par[A]]): Par[A] =
chooser(n)(i => choices(i))
answer
def chooser[A,B](p: Par[A])(choices: A => Par[B]): Par[B] =
es => {
val k = run(es)(p).get
run(es)(choices(k))
}
/* `chooser` is usually called `flatMap` or `bind`. */
def flatMap[A,B](p: Par[A])(choices: A => Par[B]): Par[B] =
es => {
val k = run(es)(p).get
run(es)(choices(k))
}
def choiceViaFlatMap[A](p: Par[Boolean])(f: Par[A], t: Par[A]): Par[A] =
flatMap(p)(b => if (b) t else f)
def choiceNViaFlatMap[A](p: Par[Int])(choices: List[Par[A]]): Par[A] =
flatMap(p)(i => choices(i))
こちらもこれまでの流れを踏まえて型シグネチャ通りに書けば問題なく。
Par[A]
型の値をA => Par[B]
を使ってPar[B]
に変換、flatMapと呼ばれる

Exercise 7.14
my impl
def join[A](a: Par[Par[A]]): Par[A] =
es => map(a)(p => run(es)(p).get)(es)
def flatMapViaJoin[A, B](p: Par[A])(choices: A => Par[B]): Par[B] =
join(map(p)(a => choices(a)))
answer
// see nonblocking implementation in `Nonblocking.scala`
def join[A](a: Par[Par[A]]): Par[A] =
es => run(es)(run(es)(a).get())
def joinViaFlatMap[A](a: Par[Par[A]]): Par[A] =
flatMap(a)(x => x)
def flatMapViaJoin[A,B](p: Par[A])(f: A => Par[B]): Par[B] =
join(map(p)(f))
自分の実装ではmapを使って最内側の計算を先にやっているように見えるが、answerの実装でも実行内容は同じようなもの?少し理解が足りない。
また、runを使い忘れている。
joinViaFlatMapはなるほどという感じ、flatMap自体がそもそも一枚外側を外すようなイメージか。

8 プロパティベースのテスト
プロパティベースのテストを可能にするライブラリでは、プログラムの振る舞いに関する仕様をテストケースの生成から切り離すことで、プログラマはプログラムの振る舞いを指定しテストケースの制約を高いレベルで定義することに専念できるようになる。制約を満たすテストケースがライブラリによって自動的に生成され、テストが実行される。

Exercise 8.3
answer
/* We can refer to the enclosing `Prop` instance with `Prop.this` */
def &&(p: Prop): Prop = new Prop {
def check = Prop.this.check && p.check
}
イミュータブルに、新しいPropを生成するときにcheckの値を判定して代入する。

Exercise 8.4
answer
def choose(start: Int, stopExclusive: Int): Gen[Int] =
Gen(State(RNG.nonNegativeInt).map(n => start + n % (stopExclusive-start)))
/* We could write this as an explicit state action, but this is far less
convenient, since it requires us to manually thread the `RNG` through the
computation. */
def choose2(start: Int, stopExclusive: Int): Gen[Int] =
Gen(State(rng => RNG.nonNegativeInt(rng) match {
case (n,rng2) => (start + n % (stopExclusive-start), rng2)
}))

Exercise 8.5
my impl
def unit[A](a: => A): Gen[A] =
Gen(State.unit(a))
def boolean: Gen[Boolean] = Gen(State.unit(true))
def listOfN[A](n: Int, g: Gen[A]): Gen[List[A]] =
//
answer
def unit[A](a: => A): Gen[A] =
Gen(State.unit(a))
def boolean: Gen[Boolean] =
Gen(State(RNG.boolean))
def choose(start: Int, stopExclusive: Int): Gen[Int] =
Gen(State(RNG.nonNegativeInt).map(n => start + n % (stopExclusive-start)))
def listOfN[A](n: Int, g: Gen[A]): Gen[List[A]] =
Gen(State.sequence(List.fill(n)(g.sample)))
RNG.boolean
やState.sequence
など既存の関数をうまく使う必要があった、自分のプロジェクトではコピーしきれていない部分もあったので修正しつつ

Exercise 8.6
my impl
def listOfN(size: Gen[Int]): Gen[List[A]] =
size.flatMap(i => Gen.listOfN(i, this))
answer
These methods are defined in the `Gen` class:
def flatMap[B](f: A => Gen[B]): Gen[B] =
Gen(sample.flatMap(a => f(a).sample))
/* A method alias for the function we wrote earlier. */
def listOfN(size: Int): Gen[List[A]] =
Gen.listOfN(size, this)
/* A version of `listOfN` that generates the size to use dynamically. */
def listOfN(size: Gen[Int]): Gen[List[A]] =
size flatMap (n => this.listOfN(n))
f(a) = Gen[B]
,f(a).sample = State[RNG, B]
なため、StateのflatMapを利用してGen[A]からGen[B]に変換することができる

Exercise 8.7
answer
def union[A](g1: Gen[A], g2: Gen[A]): Gen[A] =
boolean.flatMap(b => if (b) g1 else g2)
問題文の
結合は各ジェネレータから同じ値となる可能性があるものを取り出すという方法で行う。
という意味がつかめず。実装はわかりやすい。

Exercise 8.8
answer
def weighted[A](g1: (Gen[A],Double), g2: (Gen[A],Double)): Gen[A] = {
/* The probability we should pull from `g1`. */
val g1Threshold = g1._2.abs / (g1._2.abs + g2._2.abs)
Gen(State(RNG.double).flatMap(d =>
if (d < g1Threshold) g1._1.sample else g2._1.sample))
}
threshold(しきい値)の求め方と、新たなDouble値を生成するStateを使って使用するGen(ジェネレータ)を選ぶという方針を理解する必要がある。

Exercise 8.9
my impl
def &&(p: Prop): Prop = Prop { (n, rng) =>
this.run(n, rng) match {
case falsified: Falsified => falsified
case Passed =>
p.run(n, rng) match {
case falsified2: Falsified => falsified2
case Passed => Passed
}
}
}
def ||(p: Prop): Prop = Prop { (n, rng) =>
this.run(n, rng) match {
case Passed => Passed
case falsified: Falsified =>
p.run(n, rng) match {
case Passed => Passed
case falsified2: Falsified => falsified2
}
}
}
answer
def &&(p: Prop) = Prop {
(max,n,rng) => run(max,n,rng) match {
case Passed => p.run(max, n, rng)
case x => x
}
}
def ||(p: Prop) = Prop {
(max,n,rng) => run(max,n,rng) match {
// In case of failure, run the other prop.
case Falsified(msg, _) => p.tag(msg).run(max,n,rng)
case x => x
}
}
/* This is rather simplistic - in the event of failure, we simply prepend
* the given message on a newline in front of the existing message.
*/
def tag(msg: String) = Prop {
(max,n,rng) => run(max,n,rng) match {
case Falsified(e, c) => Falsified(msg + "\n" + e, c)
case x => x
}
}
各ケースにおいて、パターンマッチングをネストする必要はなかった。よく見れば当たり前のこと。
またこの回答ではdef tag
にて失敗ケースの結合をしているが、ここでは単にエラーメッセージの文字列を開業して新たなメッセージを追加するシンプルな例が示されている。

Exercise 8.10
my imple
def unsized: SGen[A] = SGen(i => this)
answer
def unsized: SGen[A] = SGen(_ => this)
GenをSGenに変換、とてもシンプル

Exercise 8.11
my impl
def flatMap[B](f: A => SGen[B]): SGen[B] =
SGen(i => this.forSize(i).flatMap(a => f(a).forSize(i)))
answer
case class SGen[+A](g: Int => Gen[A]) {
def apply(n: Int): Gen[A] = g(n)
def map[B](f: A => B): SGen[B] =
SGen { g(_) map f }
def flatMap[B](f: A => SGen[B]): SGen[B] = {
val g2: Int => Gen[B] = n => {
g(n) flatMap { f(_).g(n) }
}
SGen(g2)
}
def **[B](s2: SGen[B]): SGen[(A, B)] =
SGen(n => apply(n) ** s2(n))
}
Genと同じ演算をサポートのことだが、flatMap以外初見のような。

Exercise 8.12
my impl
def listOf[A](g: Gen[A]): SGen[List[A]] =
SGen(listOfN(_, g))
answer
def listOf[A](g: Gen[A]): SGen[List[A]] =
SGen(n => g.listOfN(n))
answerでは
def listOfN(size: Int): Gen[List[A]] =
Gen.listOfN(size, this)
/* A version of `listOfN` that generates the size to use dynamically. */
def listOfN(size: Gen[Int]): Gen[List[A]] =
size flatMap (n => this.listOfN(n))
のようなエイリアスを使った関数として実装しているのでこのようになる。

Exercise 8.13
answer
def listOf1[A](g: Gen[A]): SGen[List[A]] =
SGen(n => g.listOfN(n max 1))
val maxProp1 = forAll(listOf1(smallInt)) { l =>
val max = l.max
!l.exists(_ > max) // No value greater than `max` should exist in `l`
}
意外とシンプルな話だった。0以下の場合は1に変換し、検証していく過程のテストケース数なので発生確率などは特に関係ない、ということか

Exercise 8.14
my impl
val sortProp = forAll(listOf(smallInt))(l =>
l.sliding(2).forall(pair => pair(0) <= pair(1))
)
answer
val sortedProp = forAll(listOf(smallInt)) { ns =>
val nss = ns.sorted
// We specify that every sorted list is either empty, has one element,
// or has no two consecutive elements `(a,b)` such that `a` is greater than `b`.
(nss.isEmpty || nss.tail.isEmpty || !nss.zip(nss.tail).exists {
case (a,b) => a > b
})
// Also, the sorted list should have all the elements of the input list,
&& !ns.exists(!nss.contains(_))
// and it should have no elements not in the input list.
&& !nss.exists(!ns.contains(_))
}
単に要素がソートされているだけでなく、リストのすべての要素が変化していないことなどもチェックする必要がある。

Exercise 8.16
answer
/* A `Gen[Par[Int]]` generated from a list summation that spawns a new parallel
* computation for each element of the input list summed to produce the final
* result. This is not the most compelling example, but it provides at least some
* variation in structure to use for testing.
*/
val pint2: Gen[Par[Int]] = choose(-100,100).listOfN(choose(0,20)).map(l =>
l.foldLeft(Par.unit(0))((p,i) =>
Par.fork { Par.map2(p, Par.unit(i))(_ + _) }))
Exercise 8.17
answer
val forkProp = Prop.forAllPar(pint2)(i => equal(Par.fork(i), i)) tag "fork"

Exercise 8.18
answer
* `l.takeWhile(f) ++ l.dropWhile(f) == l`
* We want to enforce that `takeWhile` returns the _longest_ prefix whose elements satisfy the predicate. There are various ways to state this, but the general idea is that the remaining list, if non-empty, should start with an element that does _not_ satisfy the predicate.

パーサーコンビネータ

Exercise 9.1
my impl
def map2[A, B, C](p: Parser[A], p2: Parser[B])(f: (A, B) => C): Parser[C] =
(p ** p2).map { case (a, b) => f(a, b) }
answer
def map2[A,B,C](p: Parser[A], p2: Parser[B])(
f: (A,B) => C): Parser[C] =
map(product(p, p2))(f.tupled)
def many1[A](p: Parser[A]): Parser[List[A]] =
map2(p, many(p))(_ :: _)

Exercise 9.2
answer
`product` is associative. These two expressions are "roughly" equal:
(a ** b) ** c
a ** (b ** c)
The only difference is how the pairs are nested. The `(a ** b) ** c` parser returns an `((A,B), C)`, whereas the `a ** (b ** c)` returns an `(A, (B,C))`. We can define functions `unbiasL` and `unbiasR` to convert these nested tuples to flat 3-tuples:
def unbiasL[A,B,C](p: ((A,B), C)): (A,B,C) = (p._1._1, p._1._2, p._2)
def unbiasR[A,B,C](p: (A, (B,C))): (A,B,C) = (p._1, p._2._1, p._2._2)
With these, we can now state the associativity property:
(a ** b) ** c map (unbiasL) == a ** (b ** c) map (unbiasR)
We'll sometimes just use `~=` when there is an obvious bijection between the two sides:
(a ** b) ** c ~= a ** (b ** c)
`map` and `product` also have an interesting relationship--we can `map` either before or after taking the product of two parsers, without affecting the behavior:
a.map(f) ** b.map(g) == (a ** b) map { case (a,b) => (f(a), g(b)) }
For instance, if `a` and `b` were both `Parser[String]`, and `f` and `g` both computed the length of a string, it doesn't matter if we map over the result of `a` to compute its length, or whether we do that _after_ the product.
See chapter 12 for more discussion of these laws.

Exercise 9.3
answer
def many[A](p: Parser[A]): Parser[List[A]] =
map2(p, many(p))(_ :: _) or succeed(List())

Exercise 9.4
my impl
def listOfN[A](n: Int, p: Parser[A]): Parser[List[A]] =
n match {
case i if i <= 0 => succeed(Nil)
case ii => map2(p, listOfN(ii - 1, p))(_ :: _)
}
answer
def listOfN[A](n: Int, p: Parser[A]): Parser[List[A]] =
if (n <= 0) succeed(List())
else map2(p, listOfN(n-1, p))(_ :: _)
こちらは実装できた

Exercise 9.5
answer
// We could introduce a combinator, `wrap`:
def wrap[A](p: => Parser[A]): Parser[A]
// Then define `many` as:
def many[A](p: Parser[A]): Parser[List[A]] =
map2(p, wrap(many(p)))(_ :: _) or succeed(List())
// In the parallelism chapter, we were particularly interested in avoiding having `Par` objects that took as much time and space to build as the corresponding serial computation, and the `delay` combinator let us control this more carefully. Here, this isn't as much of a concern, and having to think carefully each time we `map2` to decide whether we need to call `wrap` seems like unnecessary friction for users of the API.
非正格な値にラップする関数wrapを用意することで、非正格性を扱うこともできる。

Exercise 9.6
answer
/* We'll just have this parser return the number of `"a"` characters read. Note that we can declare a normal value inside a for-comprehension. */
for {
digit <- "[0-9]+".r
val n = digit.toInt // we really should catch exceptions thrown by toInt and convert to parse failure
_ <- listOfN(n, char('a'))
} yield n

Exercise 9.7
my impl
def product[A, B](p: Parser[A], p2: => Parser[B]): Parser[(A, B)] =
p.flatMap(a => p2.map(b => (a, b)))
def map2[A, B, C](p: Parser[A], p2: => Parser[B])(f: (A, B) => C): Parser[C] =
p.flatMap(a => p2.map(b => f(a, b)))
answer
/*
These can be implemented using a for-comprehension, which delegates to the `flatMap` and `map` implementations we've provided on `ParserOps`, or they can be implemented in terms of these functions directly.
*/
def product[A,B](p: Parser[A], p2: => Parser[B]): Parser[(A,B)] =
flatMap(p)(a => map(p2)(b => (a,b)))
def map2[A,B,C](p: Parser[A], p2: => Parser[B])(f: (A,B) => C): Parser[C] =
for { a <- p; b <- p2 } yield f(a,b)
flatMapを使ってproductとmap2を実装する。解答例ではfor内包表記を使っている

Exercise 9.7
my impl
def product[A, B](p: Parser[A], p2: => Parser[B]): Parser[(A, B)] =
p.flatMap(a => p2.map(b => (a, b)))
def map2[A, B, C](p: Parser[A], p2: => Parser[B])(f: (A, B) => C): Parser[C] =
p.flatMap(a => p2.map(b => f(a, b)))
answer
/*
These can be implemented using a for-comprehension, which delegates to the `flatMap` and `map` implementations we've provided on `ParserOps`, or they can be implemented in terms of these functions directly.
*/
def product[A,B](p: Parser[A], p2: => Parser[B]): Parser[(A,B)] =
flatMap(p)(a => map(p2)(b => (a,b)))
def map2[A,B,C](p: Parser[A], p2: => Parser[B])(f: (A,B) => C): Parser[C] =
for { a <- p; b <- p2 } yield f(a,b)
flatMapを使ってproductとmap2を実装する。解答例ではfor内包表記を使っている

Exercise 9.8
my impl
def map[A, B](a: Parser[A])(f: A => B): Parser[B] =
a.flatMap(aa => succeed(f(aa)))
answer
def map[A,B](p: Parser[A])(f: A => B): Parser[B] = p.flatMap(a => succeed(f(a)))
この辺りの型合わせのような関数実装は多少慣れてきた

9章のp198以降はかなり自分で設計する方針の割合が大きくなってきたので省略。またある程度着手できるようになったら戻ってきたい。

モノイド
Exercise 10.1
my impl
val intAddition: Monoid[Int] = new Monoid[Int] {
def op(a1: Int, a2: Int): Int = a1 + a2
val zero = 0
}
val intMultiplication: Monoid[Int] = new Monoid[Int] {
def op(a1: Int, a2: Int): Int = a1 * a2
val zero = 1
}
val booleanOr: Monoid[Boolean] = new Monoid[Boolean] {
def op(a1: Boolean, a2: Boolean): Boolean = a1 || a2
val zero = false
}
val booleanAnd: Monoid[Boolean] = new Monoid[Boolean] {
def op(a1: Boolean, a2: Boolean): Boolean = a1 && a2
val zero = true
}
answer
val intAddition: Monoid[Int] = new Monoid[Int] {
def op(x: Int, y: Int) = x + y
val zero = 0
}
val intMultiplication: Monoid[Int] = new Monoid[Int] {
def op(x: Int, y: Int) = x * y
val zero = 1
}
val booleanOr: Monoid[Boolean] = new Monoid[Boolean] {
def op(x: Boolean, y: Boolean) = x || y
val zero = false
}
val booleanAnd: Monoid[Boolean] = new Monoid[Boolean] {
def op(x: Boolean, y: Boolean) = x && y
val zero = true
}

Exercise 9.2
my impl
def optionMonoid[A] = new Monoid[Option[A]] {
def op(a1: Option[A], a2: Option[A]): Option[A] = (a1, a2) match {
case (a: Some[A], _) => a
case (_, a: Some[A]) => a
case _ => None
}
val zero = None
}
answer
// Notice that we have a choice in how we implement `op`.
// We can compose the options in either order. Both of those implementations
// satisfy the monoid laws, but they are not equivalent.
// This is true in general--that is, every monoid has a _dual_ where the
// `op` combines things in the opposite order. Monoids like `booleanOr` and
// `intAddition` are equivalent to their duals because their `op` is commutative
// as well as associative.
def optionMonoid[A]: Monoid[Option[A]] = new Monoid[Option[A]] {
def op(x: Option[A], y: Option[A]) = x orElse y
val zero = None
}
// We can get the dual of any monoid just by flipping the `op`.
def dual[A](m: Monoid[A]): Monoid[A] = new Monoid[A] {
def op(x: A, y: A): A = m.op(y, x)
val zero = m.zero
}
// Now we can have both monoids on hand:
def firstOptionMonoid[A]: Monoid[Option[A]] = optionMonoid[A]
def lastOptionMonoid[A]: Monoid[Option[A]] = dual(firstOptionMonoid)
パターンマッチング などせずともorElse
で対応できた

Exercise 10.3
my impl
def endoMonoid[A]: Monoid[A => A] = new Monoid[A => A] {
def op(a1: A => A, a2: A => A): A => A = a => a1(a2(a))
val zero = a => a
}
answer
// There is a choice of implementation here as well.
// Do we implement it as `f compose g` or `f andThen g`? We have to pick one.
// We can then get the other one using the `dual` construct (see previous answer).
def endoMonoid[A]: Monoid[A => A] = new Monoid[A => A] {
def op(f: A => A, g: A => A) = f compose g
val zero = (a: A) => a
}
関数合成composeが用意されている

Exercise 10.4
my impl
def monoidLaws[A](m: Monoid[A], gen: Gen[A]): Prop =
Prop.forAll(gen)(a => m.op(a, m.zero) == a && m.op(m.zero, a) == a)
answer
import fpinscala.testing._
import Prop._
def monoidLaws[A](m: Monoid[A], gen: Gen[A]): Prop =
// Associativity
forAll(for {
x <- gen
y <- gen
z <- gen
} yield (x, y, z))(p =>
m.op(p._1, m.op(p._2, p._3)) == m.op(m.op(p._1, p._2), p._3)) &&
// Identity
forAll(gen)((a: A) =>
m.op(a, m.zero) == a && m.op(m.zero, a) == a)
モノイド則をプロパティベースでテストする。
自分の実装では単位元のテストしかカバーできていないが、結合則の方のためには、複数の型Aの値をfor内包分などで生成して行えば良い

Exercise 10.5
my impl
def foldMap[A, B](as: List[A], m: Monoid[B])(f: A => B): B =
concatenate(as.map(f), m)
answer
// Notice that this function does not require the use of `map` at all.
def foldMap[A, B](as: List[A], m: Monoid[B])(f: A => B): B =
as.foldLeft(m.zero)((b, a) => m.op(b, f(a)))
Notice that this function does not require the use of
map
at all.
mapを使う必要がない、とのこと

Exercise 10.6
answer
// The function type `(A, B) => B`, when curried, is `A => (B => B)`.
// And of course, `B => B` is a monoid for any `B` (via function composition).
def foldRight[A, B](as: List[A])(z: B)(f: (A, B) => B): B =
foldMap(as, endoMonoid[B])(f.curried)(z)
// Folding to the left is the same except we flip the arguments to
// the function `f` to put the `B` on the correct side.
// Then we have to also "flip" the monoid so that it operates from left to right.
def foldLeft[A, B](as: List[A])(z: B)(f: (B, A) => B): B =
foldMap(as, dual(endoMonoid[B]))(a => b => f(b, a))(z)

10.3 結合性と並列性
モノイドの演算が結合的であるということは、リストなどのデータ構造を畳み込む方法を選択できるということです。前節で説明したように、foldLeftまたはfoldRightを使って演算を左または右に結合すれば、リストを徐々に畳み込むことができます。しかし、モノイドを利用できる場合は、平衡畳み込み(balanced fold)を使ってリストを畳み込むことができます。演算によっては、このほうが効率的であり、並列化も可能となります。
foldLeftやfoldRightでは畳み込みごとに中間文字列が生成され、すぐに削除される事になる。シーケンスを半分に分けてつなぎ合わせる方(平衡畳み込み)がこの無駄が減り、効率的になる。

Exercise 10.7
my impl
def foldMapV[A, B](v: IndexedSeq[A], m: Monoid[B])(f: A => B): B =
if (v.isEmpty) m.zero
else if (v.size == 1) f(v.head)
else {
val left = foldMapV(v.slice(0, v.length / 2), m)(f)
val right = foldMapV(v.slice(v.length / 2, v.length), m)(f)
m.op(left, right)
}
answer
def foldMapV[A, B](as: IndexedSeq[A], m: Monoid[B])(f: A => B): B =
if (as.length == 0)
m.zero
else if (as.length == 1)
f(as(0))
else {
val (l, r) = as.splitAt(as.length / 2)
m.op(foldMapV(l, m)(f), foldMapV(r, m)(f))
}
ほぼ問題なく。平衡畳み込みの実装

Exercise 10.8
answer
// This ability to 'lift' a monoid any monoid to operate within
// some context (here `Par`) is something we'll discuss more in
// chapters 11 & 12
def par[A](m: Monoid[A]): Monoid[Par[A]] = new Monoid[Par[A]] {
def zero = Par.unit(m.zero)
def op(a: Par[A], b: Par[A]) = a.map2(b)(m.op)
}
// we perform the mapping and the reducing both in parallel
def parFoldMap[A,B](v: IndexedSeq[A], m: Monoid[B])(f: A => B): Par[B] =
Par.parMap(v)(f).flatMap { bs =>
foldMapV(bs, par(m))(b => Par.async(b))
}
並列化バージョンのfoldMap

Exercise 10.9
foldMapを使って特定のIndexedSeq[Int]が順序付けされているかどうかを割り出せ。これについては、独創的なMonoidを考え出す必要があるだろう。
answer
// This implementation detects only ascending order,
// but you can write a monoid that detects both ascending and descending
// order if you like.
def ordered(ints: IndexedSeq[Int]): Boolean = {
// Our monoid tracks the minimum and maximum element seen so far
// as well as whether the elements are so far ordered.
val mon = new Monoid[Option[(Int, Int, Boolean)]] {
def op(o1: Option[(Int, Int, Boolean)], o2: Option[(Int, Int, Boolean)]) =
(o1, o2) match {
// The ranges should not overlap if the sequence is ordered.
case (Some((x1, y1, p)), Some((x2, y2, q))) =>
Some((x1 min x2, y1 max y2, p && q && y1 <= x2))
case (x, None) => x
case (None, x) => x
}
val zero = None
}
// The empty sequence is ordered, and each element by itself is ordered.
foldMapV(ints, mon)(i => Some((i, i, true))).map(_._3).getOrElse(true)
}

Exercise 10.7
answer
val wcMonoid: Monoid[WC] = new Monoid[WC] {
// The empty result, where we haven't seen any characters yet.
val zero = Stub("")
def op(a: WC, b: WC) = (a, b) match {
case (Stub(c), Stub(d)) => Stub(c + d)
case (Stub(c), Part(l, w, r)) => Part(c + l, w, r)
case (Part(l, w, r), Stub(c)) => Part(l, w, r + c)
case (Part(l1, w1, r1), Part(l2, w2, r2)) =>
Part(l1, w1 + (if ((r1 + l2).isEmpty) 0 else 1) + w2, r2)
}
}
場合分けが多すぎるように思えて答えを確認。例えばcase (Stub(c), Part(l, w, r)) => Part(c + l, w, r)
のように、c + l
の中で単語が存在する場合は、確認を後回しにする、という方針?

Exercise 10.11
my impl
def countWords(s: String): Int = {
def loop(ss: String): WC = {
if (ss.isEmpty) wcMonoid.zero
else if (ss.length == 1) Stub(ss)
else {
val (l, r) = ss.splitAt(s.length / 2)
wcMonoid.op(loop(l), loop(r))
}
}
val m = loop(s)
m match {
case Part(lStub, words, rStub) =>
words + (if (lStub.isEmpty) 0 else 1) + (if (rStub.isEmpty) 0 else 1)
case Stub(chars) => if (chars.isEmpty) 0 else 1
}
}
answer
def count(s: String): Int = {
def wc(c: Char): WC =
if (c.isWhitespace)
Part("", 0, "")
else
Stub(c.toString)
def unstub(s: String) = s.length min 1
foldMapV(s.toIndexedSeq, wcMonoid)(wc) match {
case Stub(s) => unstub(s)
case Part(l, w, r) => unstub(l) + w + unstub(r)
}
}

Exercise 10.12
my impl
val listFoldable = new Foldable[List] {
def foldRight[A, B](as: List[A])(z: B)(f: (A, B) => B): B = as match {
case head :: tl => f(head, foldRight(tl)(z)(f))
case Nil => z
}
def foldLeft[A, B](as: List[A])(z: B)(f: (B, A) => B): B = as match {
case head :: tl => foldLeft(tl)(f(z, head))(f)
case Nil => z
}
def foldMap[A, B](as: List[A])(f: A => B)(mb: Monoid[B]): B = as match {
case head :: tl => mb.op(f(head), foldMap(tl)(f)(mb))
case Nil => mb.zero
}
def concatenate[A](as: List[A])(m: Monoid[A]): A = as match {
case head :: tl => m.op(head, concatenate(tl)(m))
case Nil => m.zero
}
}
answer
trait Foldable[F[_]] {
def foldRight[A, B](as: F[A])(z: B)(f: (A, B) => B): B =
foldMap(as)(f.curried)(endoMonoid[B])(z)
def foldLeft[A, B](as: F[A])(z: B)(f: (B, A) => B): B =
foldMap(as)(a => (b: B) => f(b, a))(dual(endoMonoid[B]))(z)
def foldMap[A, B](as: F[A])(f: A => B)(mb: Monoid[B]): B =
foldRight(as)(mb.zero)((a, b) => mb.op(f(a), b))
def concatenate[A](as: F[A])(m: Monoid[A]): A =
foldLeft(as)(m.zero)(m.op)
}
object ListFoldable extends Foldable[List] {
override def foldRight[A, B](as: List[A])(z: B)(f: (A, B) => B) =
as.foldRight(z)(f)
override def foldLeft[A, B](as: List[A])(z: B)(f: (B, A) => B) =
as.foldLeft(z)(f)
override def foldMap[A, B](as: List[A])(f: A => B)(mb: Monoid[B]): B =
foldLeft(as)(mb.zero)((b, a) => mb.op(b, f(a)))
}
object IndexedSeqFoldable extends Foldable[IndexedSeq] {
import Monoid._
override def foldRight[A, B](as: IndexedSeq[A])(z: B)(f: (A, B) => B) =
as.foldRight(z)(f)
override def foldLeft[A, B](as: IndexedSeq[A])(z: B)(f: (B, A) => B) =
as.foldLeft(z)(f)
override def foldMap[A, B](as: IndexedSeq[A])(f: A => B)(mb: Monoid[B]): B =
foldMapV(as, mb)(f)
}
object StreamFoldable extends Foldable[Stream] {
override def foldRight[A, B](as: Stream[A])(z: B)(f: (A, B) => B) =
as.foldRight(z)(f)
override def foldLeft[A, B](as: Stream[A])(z: B)(f: (B, A) => B) =
as.foldLeft(z)(f)
}

Exercise 10.13
my impl
sealed trait Tree[+A]
case class Leaf[A](value: A) extends Tree[A]
case class Branch[A](left: Tree[A], right: Tree[A]) extends Tree[A]
object TreeFoldable extends Foldable[Tree] {
override def foldRight[A, B](as: Tree[A])(z: B)(f: (A, B) => B): B =
as match {
case Branch(left, right) => foldRight(left)(foldRight(right)(z)(f))(f)
case Leaf(value) => f(value, z)
}
override def foldLeft[A, B](as: Tree[A])(z: B)(f: (B, A) => B): B = as match {
case Branch(left, right) => foldLeft(right)(foldLeft(left)(z)(f))(f)
case Leaf(value) => f(z, value)
}
override def foldMap[A, B](as: Tree[A])(f: A => B)(mb: Monoid[B]): B =
as match {
case Branch(left, right) =>
mb.op(foldMap(left)(f)(mb), foldMap(right)(f)(mb))
case Leaf(value) => f(value)
}
}
answer
sealed trait Tree[+A]
case class Leaf[A](value: A) extends Tree[A]
case class Branch[A](left: Tree[A], right: Tree[A]) extends Tree[A]
object TreeFoldable extends Foldable[Tree] {
override def foldMap[A, B](as: Tree[A])(f: A => B)(mb: Monoid[B]): B = as match {
case Leaf(a) => f(a)
case Branch(l, r) => mb.op(foldMap(l)(f)(mb), foldMap(r)(f)(mb))
}
override def foldLeft[A, B](as: Tree[A])(z: B)(f: (B, A) => B) = as match {
case Leaf(a) => f(z, a)
case Branch(l, r) => foldLeft(r)(foldLeft(l)(z)(f))(f)
}
override def foldRight[A, B](as: Tree[A])(z: B)(f: (A, B) => B) = as match {
case Leaf(a) => f(a, z)
case Branch(l, r) => foldRight(l)(foldRight(r)(z)(f))(f)
}
}
// Notice that in `TreeFoldable.foldMap`, we don't actually use the `zero`
// from the `Monoid`. This is because there is no empty tree.
// This suggests that there might be a class of types that are foldable
// with something "smaller" than a monoid, consisting only of an
// associative `op`. That kind of object (a monoid without a `zero`) is
// called a semigroup.
Tree構造のFoldableインスタンスの実装。型に合うように当てはめて問題なさそう。

Exercise 10.14
my impl
object OptionFoldable extends Foldable[Option] {
override def foldRight[A, B](as: Option[A])(z: B)(f: (A, B) => B): B =
as match {
case None => z
case Some(value) => f(value, z)
}
override def foldLeft[A, B](as: Option[A])(z: B)(f: (B, A) => B): B =
as match {
case None => z
case Some(value) => f(z, value)
}
override def foldMap[A, B](as: Option[A])(f: A => B)(mb: Monoid[B]): B =
as match {
case None => mb.zero
case Some(value) => f(value)
}
}
answer
object OptionFoldable extends Foldable[Option] {
override def foldMap[A, B](as: Option[A])(f: A => B)(mb: Monoid[B]): B =
as match {
case None => mb.zero
case Some(a) => f(a)
}
override def foldLeft[A, B](as: Option[A])(z: B)(f: (B, A) => B) = as match {
case None => z
case Some(a) => f(z, a)
}
override def foldRight[A, B](as: Option[A])(z: B)(f: (A, B) => B) = as match {
case None => z
case Some(a) => f(a, z)
}
}

Exercise 10.15
answer
def toList[A](as: F[A]): List[A] =
foldRight(as)(List[A]())(_ :: _)
アクシデント的に答えを見てしまったため。
畳み込みながらリストを生成する。

10.16
answer
def productMonoid[A,B](A: Monoid[A], B: Monoid[B]): Monoid[(A, B)] =
new Monoid[(A, B)] {
def op(x: (A, B), y: (A, B)) =
(A.op(x._1, y._1), B.op(x._2, y._2))
val zero = (A.zero, B.zero)
}

Exercise 10.17
my impl
def functionMonoid[A, B](B: Monoid[B]): Monoid[A => B] =
new Monoid[A => B] {
def op(a1: A => B, a2: A => B): A => B = a => B.op(a1(a), a2(a))
def zero: A => B = _ => B.zero
}
answer
def functionMonoid[A,B](B: Monoid[B]): Monoid[A => B] =
new Monoid[A => B] {
def op(f: A => B, g: A => B) = a => B.op(f(a), g(a))
val zero: A => B = a => B.zero
}
モノイドの合成、Bのモノイドを使ってA => B
関数のモノイドインスタンスを記述する。

Exercise 10.18
answer
def bag[A](as: IndexedSeq[A]): Map[A, Int] =
foldMapV(as, mapMergeMonoid[A, Int](intAddition))((a: A) => Map(a -> 1))
要素をキー、その個数を値としたMapを生成するbag関数の実装。
foldMapを使用し、(a: A) => Map(a -> 1)
を関数として与え、Mapをモノイドで結合していく。

Exercise 11.1
my impl
val ParMonad = new Monad[Par] {
def unit[A](a: => A): Par[A] = Par.unit(a)
def flatMap[A, B](ma: Par[A])(f: A => Par[B]): Par[B] = flatMap(ma)(f)
}
// val ParserMonad = new Monad[Parsers] {
// //
// }
val OptionMonad = new Monad[Option] {
def unit[A](a: => A): Option[A] = Some(a)
def flatMap[A, B](ma: Option[A])(f: A => Option[B]): Option[B] =
ma.flatMap(f)
}
val StreamMonad = new Monad[Stream] {
def unit[A](a: => A): Stream[A] = Stream(a)
def flatMap[A, B](ma: Stream[A])(f: A => Stream[B]): Stream[B] =
ma.flatMap(f)
}
val ListMonad = new Monad[List] {
def unit[A](a: => A): List[A] = List(a)
def flatMap[A, B](ma: List[A])(f: A => List[B]): List[B] = flatMap(ma)(f)
}
answer
val parMonad = new Monad[Par] {
def unit[A](a: => A) = Par.unit(a)
def flatMap[A,B](ma: Par[A])(f: A => Par[B]) = Par.flatMap(ma)(f)
}
def parserMonad[P[+_]](p: Parsers[P]) = new Monad[P] {
def unit[A](a: => A) = p.succeed(a)
def flatMap[A,B](ma: P[A])(f: A => P[B]) = p.flatMap(ma)(f)
}
val optionMonad = new Monad[Option] {
def unit[A](a: => A) = Some(a)
def flatMap[A,B](ma: Option[A])(f: A => Option[B]) = ma flatMap f
}
val streamMonad = new Monad[Stream] {
def unit[A](a: => A) = Stream(a)
def flatMap[A,B](ma: Stream[A])(f: A => Stream[B]) = ma flatMap f
}
val listMonad = new Monad[List] {
def unit[A](a: => A) = List(a)
def flatMap[A,B](ma: List[A])(f: A => List[B]) = ma flatMap f
}
Parserだけimportの仕方がわからなかったが、Parsersを使いParser型コンストラクタのため[P[+_]]
のようなジェネリックを使っている。
自分の写経ではParseErrorをクラスとして定義しておらずParsersの型コンストラクタとして与えられているだけなので以下のように記述してコンパイルエラーを消した
def parserMonad[P[+_]](p: Parsers[_, P]) = new Monad[P] {
def unit[A](a: => A) = p.succeed(a)
def flatMap[A, B](ma: P[A])(f: A => P[B]) = p.flatMap(ma)(f)
}

Exercise 11.2
answer
// Since `State` is a binary type constructor, we need to partially apply it
// with the `S` type argument. Thus, it is not just one monad, but an entire
// family of monads, one for each type `S`. One solution is to create a class
// `StateMonads` that accepts the `S` type argument and then has a _type member_
// for the fully applied `State[S, A]` type inside:
class StateMonads[S] {
type StateS[A] = State[S, A]
// We can then declare the monad for the `StateS` type constructor:
val monad = new Monad[StateS] {
def unit[A](a: => A): State[S, A] = State(s => (a, s))
override def flatMap[A,B](st: State[S, A])(f: A => State[S, B]): State[S, B] =
st flatMap f
}
}
// But we don't have to create a full class like `StateMonads`. We can create
// an anonymous class inline, inside parentheses, and project out its type member `f`.
// This is sometimes called a "type lambda", since it's very similar to a type-level
// anonymous function.
def stateMonad[S] = new Monad[({type f[x] = State[S, x]})#f] {
def unit[A](a: => A): State[S, A] = State(s => (a, s))
override def flatMap[A,B](st: State[S, A])(f: A => State[S, B]): State[S, B] =
st flatMap f
}

Exercise 11.3
my impl
def sequence[A](lma: List[F[A]]): F[List[A]] = lma match {
case head :: tl => flatMap(head)(a => map(sequence(tl))(a :: _))
case Nil => unit(List())
}
def traverse[A, B](la: List[A])(f: A => F[B]): F[List[B]] =
sequence(la.map(f))
answer
def sequence[A](lma: List[F[A]]): F[List[A]] =
lma.foldRight(unit(List[A]()))((ma, mla) => map2(ma, mla)(_ :: _))
def traverse[A,B](la: List[A])(f: A => F[B]): F[List[B]] =
la.foldRight(unit(List[B]()))((a, mlb) => map2(f(a), mlb)(_ :: _))
/**
* 'Balanced' sequencing, which should behave like `sequence`,
* but it can use less stack for some data types. We'll see later
* in this chapter how the monad _laws_ let us conclude both
* definitions 'mean' the same thing.
*/
def bsequence[A](ms: Seq[F[A]]): F[IndexedSeq[A]] = {
if (ms.isEmpty) point(Vector())
else if (ms.size == 1) ms.head.map(Vector(_))
else {
val (l,r) = ms.toIndexedSeq.splitAt(ms.length / 2)
map2(bsequence(l), bsequence(r))(_ ++ _)
}
}
foldRightやmap2を活用して、という寸法

Exercise 11.4
my impl
def replicateM[A](n: Int, ma: F[A]): F[List[A]] =
sequence(List.fill(n)(ma))
answer
// Recursive version:
def _replicateM[A](n: Int, ma: F[A]): F[List[A]] =
if (n <= 0) unit(List[A]()) else map2(ma, _replicateM(n - 1, ma))(_ :: _)
// Using `sequence` and the `List.fill` function of the standard library:
def replicateM[A](n: Int, ma: F[A]): F[List[A]] =
sequence(List.fill(n)(ma))

Exercise 11.5
answer
For
List
, thereplicateM
function will generate a list of lists. It will contain all the lists of lengthn
with elements selected from the input list.For
Option
, it will generate eitherSome
orNone
based on whether the input isSome
orNone
. TheSome
case will contain a list of lengthn
that repeats the element in the inputOption
.The general meaning of
replicateM
is described well by the implementationsequence(List.fill(n)(ma))
. It repeats thema
monadic valuen
times and gathers the results in a single value, where the monadF
determines how values are actually combined.

Exercise 11.6
answer
/*
For `Par`, `filterM` filters a list, applying the functions in
parallel; for `Option`, it filters a list, but allows
the filtering function to fail and abort the filter
computation; for `Gen`, it produces a generator for
subsets of the input list, where the function `f` picks a
'weight' for each element (in the form of a
`Gen[Boolean]`)
*/
def filterM[A](ms: List[A])(f: A => F[Boolean]): F[List[A]] =
ms match {
case Nil => unit(Nil)
case h :: t => flatMap(f(h))(b =>
if (!b) filterM(t)(f)
else map(filterM(t)(f))(h :: _))
}

Exercise 11.7
my impl
def compose[A, B, C](f: A => F[B], g: B => F[C]): A => F[C] =
a => flatMap(f(a))(g)
answer
def compose[A,B,C](f: A => F[B], g: B => F[C]): A => F[C] =
a => flatMap(f(a))(g)

Exercise 11.8
answer
def flatMap[A,B](ma: F[A])(f: A => F[B]): F[B] =
compose((_:Unit) => ma, f)(())
composeをプリミティブとしてflatMapを実装する。composeの1つ目の引数はUnitを引数に取る関数(_:Unit) => ma
を与え、composeで合成された関数を実行()
して、F[B]
を求める。

Exercise 11.9
answer
Let's rewrite the following in terms of `flatMap`:
compose(compose(f, g), h) == compose(f, compose(g, h))
a => flatMap(compose(f, g)(a))(h) == a => flatMap(f(a))(compose(g, h))
a => flatMap((b => flatMap(f(b))(g))(a))(h) == a => flatMap(f(a))(b => flatMap(g(b))(h))
So far we have just expanded the definition of `compose`. Equals substituted for equals.
Let's simplify the left side a little:
a => flatMap(flatMap(f(a))(g))(h) == a => flatMap(f(a))(b => flatMap(g(b))(h))
Let's simplify again by eliminating the `a` argument and substituting a hypothetical value `x` for `f(a)`:
flatMap(flatMap(x)(g))(h) == flatMap(x)(b => flatMap(g(b))(h))
This now looks exactly like the monad law stated in terms of `flatMap`, just with different names:
flatMap(flatMap(x)(f))(g) == flatMap(x)(a => flatMap(f(a))(g))
Q.E.D.

Exercise 11.10
answer
// We simply substitute the definition of `compose` in terms of `flatMap`.
compose(f, unit)(v) == f(v) // for all functions f and values v
(a => flatMap(f(a))(unit))(v) == f(v) // Expand `compose`
flatMap(f(v))(unit) == f(v) // Simplify function application
flatMap(x)(unit) == x // Abstract out `f(v)`
compose(unit, f)(x) == f(x)
flatMap(unit(x))(f) == f(x) // Expand `compose`
Q.E.D.

Exercise 11.11
answer
For `Option`, we again consider both cases `None` and `Some` and expand the equation.
The monadic `unit` is the `Some(_)` constructor.
// Left identity is trivially true for None:
flatMap(None)(Some(_)) == None
// And here it is for Some:
flatMap(Some(v))(Some(_)) == Some(v)
// Substitute the definition of `flatMap`:
Some(v) == Some(v)
// Right identity is just as easy for None:
flatMap(Some(None))(f) == f(None)
// Substitute definition of flatMap:
f(None) == f(None)
// And for Some:
flatMap(Some(Some(v)))(f) == f(Some(v))
// Substitute definition of flatMap:
f(Some(v)) == f(Some(v))

Exercise 11.12
my impl
def join[A](mma: F[F[A]]): F[A] = flatMap(mma)(ma => ma)
answer
def join[A](mma: F[F[A]]): F[A] = flatMap(mma)(ma => ma)

Exercise 11.13
my impl
def flatMapViaJoinAndMap[A, B](ma: F[A])(f: A => F[B]): F[B] =
join(map(ma)(f))
answer
def flatMap[A,B](ma: F[A])(f: A => F[B]) =
join(map(ma)(f))
def compose[A,B,C](f: A => F[B], g: B => F[C]): A => F[C] =
a => join(map(f(a))(g))

Exercise 11.14
answer
We can look at the associative law in terms of `flatMap` from another perspective. It says that `x.flatMap(f).flatMap(g)` is equal to `x.flatMap(a => f(a).flatMap(g))` _for all_ choices of `f` and `g`. So let's pick a particular `f` and `g` that's easy to think about. We can just pick the identity function:
x.flatMap(z => z).flatMap(z => z) == x.flatMap(a => a.flatMap(z => z))
And of course, flatMapping with the identify function is `join`! The associative law can now be stated as:
join(join(x)) == x.flatMap(join)
And we know that `flatMap` is "map, then join," so let's eliminate this last call to `flatMap`:
join(join(x)) == join(map(x)(join))
The identity laws in terms of `join` are:
join(map(x)(unit)) == x
join(unit(x)) == x
This follows from the definition of `join` and the identity laws in terms of `flatMap`:
flatMap(x)(unit) == x
flatMap(unit(x))(f) == f(x)
For the second law, we simply substitute the identity function for `f`, which gives us `join`.
Let's make a fast-and-loose proof for this version of the associative law using the `List` monad as an example. Of course, `join` in the `List` monad is just _list concatenation_:
scala> listMonad.join(List(List(1, 2), List(3, 4)))
res0: List[Int] = List(1, 2, 3, 4)
Now let's say we have some lists, nested to a depth of three:
val ns: List[List[List[Int]]] =
List(List(List(1,2), List(3,4)),
List(List(), List(5)))
If we `join` this list, the outer lists get concatenated and we have a list of lists two levels deep:
scala> ns.flatten
res1: List[List[Int]] = List(List(1, 2), List(3, 4), List(), List(5))
If we instead _map_ `join` over it, we get a different nesting but again two levels deep. This flattens the _inner_ lists.
scala> ns.map(listMonad.join)
res2: List[List[Int]] = List(List(1, 2, 3, 4), List(5))
And then joining `res1` should be the same as joining `res2`:
scala> listMonad.join(res1) == listMonad.join(res2)
res3: Boolean = true
So all that the associative law is saying for the `List` monad is that concatenating the outer lists and then the inner ones (`join(join(ns))`) is the same as first concatenating the inner lists and then the outer ones (`join(ns.map(join))`).

Exercise 11.15
answer
We can state the associative law in terms of `join`:
join(join(x)) == join(map(x)(join))
For `Par`, the `join` combinator means something like "make the outer thread wait for the inner one to finish." What this law is saying is that if you have threads starting threads three levels deep, then joining the inner threads and then the outer ones is the same as joining the outer threads and then the inner ones.
For `Parser`, the `join` combinator is running the outer parser to produce a `Parser`, then running the inner `Parser` _on the remaining input_. The associative law is saying, roughly, that only the _order_ of nesting matters, since that's what affects the order in which the parsers are run.

Exercise 11.16
answer
Recall the identity laws:
left identity: flatMap(unit(x))(f) == f(x)
right identity: flatMap(x)(unit) == x
The left identity law for `Gen`:
The law states that if you take the values generated by `unit(x)` (which are always `x`) and apply `f` to those values, that's exactly the same as the generator returned by `f(x)`.
The right identity law for `Gen`:
The law states that if you apply `unit` to the values inside the generator `x`, that does not in any way differ from `x` itself.
The left identity law for `List`:
The law says that wrapping a list in a singleton `List` and then flattening the result is the same as doing nothing.
The right identity law for `List`:
The law says that if you take every value in a list, wrap each one in a singleton `List`, and then flatten the result, you get the list you started with.

Exercise 11.17
my impl
case class Id[A](value: A) {
def flatMap[B](f: A => Id[B]): Id[B] = f(value)
def map[B](f: A => B): Id[B] = Id(f(value))
}
val IdMonad = new Monad[Id] {
def unit[A](a: => A): Id[A] = Id(a)
def flatMap[A, B](ma: Id[A])(f: A => Id[B]): Id[B] = ma.flatMap(f)
}
answer
case class Id[A](value: A) {
def map[B](f: A => B): Id[B] = Id(f(value))
def flatMap[B](f: A => Id[B]): Id[B] = f(value)
}
object Id {
val idMonad = new Monad[Id] {
def unit[A](a: => A) = Id(a)
def flatMap[A,B](ida: Id[A])(f: A => Id[B]): Id[B] = ida flatMap f
}
}

Exercise 11.18
answer
`replicateM` for `State` repeats the same state transition a number of times and returns a list of the results. It's not passing the same starting state many times, but chaining the calls together so that the output state of one is the input state of the next.
`map2` works similarly in that it takes two state transitions and feeds the output state of one to the input of the other. The outputs are not put in a list, but combined with a function `f`.
`sequence` takes an entire list of state transitions and does the same kind of thing as `replicateM`: it feeds the output state of the first state transition to the input state of the next, and so on. The results are accumulated in a list.

Exercise 11.19
answer
// Getting and setting the same state does nothing:
getState.flatMap(setState) == unit(())
// written as for-comprehension:
for {
x <- getState
_ <- setState(x)
} yield ()
// Setting the state to `s` and getting it back out yields `s`.
setState(s).flatMap(_ => getState) == unit(s)
// alternatively:
for {
_ <- setState(s)
x <- getState
} yield x

Exercise 11.20
answer
object Reader {
def readerMonad[R] = new Monad[({ type f[x] = Reader[R, x] })#f] {
def unit[A](a: => A): Reader[R, A] = Reader(_ => a)
def flatMap[A, B](st: Reader[R, A])(f: A => Reader[R, B]): Reader[R, B] =
Reader(r => f(st.run(r)).run(r))
}
// A primitive operation for it would be simply to ask for the `R` argument:
def ask[R]: Reader[R, R] = Reader(r => r)
}
// The action of Reader's `flatMap` is to pass the `r` argument along to both the
// outer Reader and also to the result of `f`, the inner Reader. Similar to how
// `State` passes along a state, except that in `Reader` the "state" is read-only.
// The meaning of `sequence` here is that if you have a list of functions, you can
// turn it into a function that takes one argument and passes it to all the functions
// in the list, returning a list of the results.
// The meaning of `join` is simply to pass the same value as both arguments to a
// binary function.
// The meaning of `replicateM` is to apply the same function a number of times to
// the same argument, returning a list of the results. Note that if this function
// is _pure_, (which it should be), this can be exploited by only applying the
// function once and replicating the result instead of calling the function many times.
// This means the Reader monad can override replicateM to provide a very efficient
// implementation.
Reader の
flatMap
の動作は、引数r
を外側の Reader と内側の Reader の結果であるf
の両方に渡すことである。これはState
が状態を渡すのと似ているが、Reader
では "状態" が読み込み専用であることが異なる。ここでの
sequence
の意味は、関数のリストがある場合、1つの引数を受け取って、リスト内のすべての関数に引数を渡し、その結果のリストを返す関数にすることができる、ということである。結合`の意味は、単に2進数の関数に両方の引数として同じ値を渡すことである。
replicateM` の意味は、同じ引数に同じ関数を何度も適用して、その結果のリストを返すことである。この関数が pure である場合 (そうであるべき)、関数を何度も呼び出す代わりに、関数を一度だけ適用して結果を複製することで、これを悪用することができることに注意してください。これは、ReaderモナドがreplicateMをオーバーライドして、非常に効率的な
を実装しています。

アプリカティブファンクタとトラバーサルファンクタ
モナドほど強力ではないが、モナドより汎用的な抽象概念としてのアプリカティブファンクタ。
ファンクタではmapをプリミティブとするが、unitとmap2をプリミティブとするアプリカティブファンクタ。
アプリカティブファンクタには、自動的にファンクタの性質が含まれる(unitとmap2があればそこからmapを実装できる)
モナドではunitとflatMapをプリミティブとして派生するコンビネータを生成するが、map2の実装はflatMapを使わなくても行える。そのため、モナドより汎用的にアプリカティブファンクタを実装できる。

Exercise 12.1
my impl
def sequence[A](fas: List[F[A]]): F[List[A]] =
traverse(fas)(fa => fa)
def replicateM[A](n: Int, fa: F[A]): F[List[A]] =
sequence(List.fill(n)(fa))
def product[A, B](fa: F[A], fb: F[B]): F[(A, B)] =
map2(fa, fb)((_, _))
answer
def sequence[A](fas: List[F[A]]): F[List[A]] =
traverse(fas)(fa => fa)
def replicateM[A](n: Int, fa: F[A]): F[List[A]] =
sequence(List.fill(n)(fa))
def product[A,B](fa: F[A], fb: F[B]): F[(A,B)] =
map2(fa, fb)((_,_))

Exercise 12.2
answer
trait Applicative[F[_]] extends Functor[F] {
// `map2` is implemented by first currying `f` so we get a function
// of type `A => B => C`. This is a function that takes `A` and returns
// another function of type `B => C`. So if we map `f.curried` over an
// `F[A]`, we get `F[B => C]`. Passing that to `apply` along with the
// `F[B]` will give us the desired `F[C]`.
def map2[A, B, C](fa: F[A], fb: F[B])(f: (A, B) => C): F[C] =
apply(map(fa)(f.curried), fb)
// We simply use `map2` to lift a function into `F` so we can apply it
// to both `fab` and `fa`. The function being lifted here is `_(_)`,
// which is the same as the lambda notation `(f, x) => f(x)`. That is,
// It's a function that takes two arguments:
// 1. A function `f`
// 2. An argument `x` to that function
// and it simply applies `f` to `x`.
def apply[A, B](fab: F[A => B])(fa: F[A]): F[B] =
map2(fab, fa)(_(_))
def unit[A](a: => A): F[A]
def map[A, B](fa: F[A])(f: A => B): F[B] =
apply(unit(f))(fa)
}

Exercise 12.3
my impl
def map3[A, B, C, D](fa: F[A], fb: F[B], fc: F[C])(f: (A, B, C) => D): F[D] =
apply(apply(map(fa)(f.curried))(fb))(fc)
def map4[A, B, C, D, E](fa: F[A], fb: F[B], fc: F[C], fd: F[D])(
f: (A, B, C, D) => E
): F[E] =
apply(apply(apply(map(fa)(f.curried))(fb))(fc))(fd)
answer
/*
The pattern is simple. We just curry the function
we want to lift, pass the result to `unit`, and then `apply`
as many times as there are arguments.
Each call to `apply` is a partial application of the function
*/
def map3[A,B,C,D](fa: F[A],
fb: F[B],
fc: F[C])(f: (A, B, C) => D): F[D] =
apply(apply(apply(unit(f.curried))(fa))(fb))(fc)
def map4[A,B,C,D,E](fa: F[A],
fb: F[B],
fc: F[C],
fd: F[D])(f: (A, B, C, D) => E): F[E]
apply(apply(apply(apply(unit(f.curried))(fa))(fb))(fc))(fd)
mapは内部的にはapply(unit(f)(fa))
であり、そのまま表現している。

Exercise 12.4
answer
This transposes the list! That is, we start with a list of rows, each of which is possibly infinite in length. We get back a single row, where each element is the column of values at that position. Try it yourself in the REPL.

Exercise 12.5
my impl
def eitherMonad[E] =
new Monad[({ type f[x] = Either[E, x] })#f] {
def unit[A](a: => A): Either[E, A] = Right(a)
override def flatMap[A, B](
ma: Either[E, A]
)(f: A => Either[E, B]): Either[E, B] = ma match {
case Right(value) => f(value)
case Left(e) => Left(e)
}
}
answer
def eitherMonad[E]: Monad[({type f[x] = Either[E, x]})#f] =
new Monad[({type f[x] = Either[E, x]})#f] {
def unit[A](a: => A): Either[E, A] = Right(a)
def flatMap[A,B](eea: Either[E, A])(f: A => Either[E, B]) = eea match {
case Right(a) => f(a)
case Left(e) => Left(e)
}
}

Exercise 12.6
my impl
def validationApplicative[E] =
new Applicative[({ type f[x] = Validation[E, x] })#f] {
def unit[A](a: => A): Validation[E, A] = Success(a)
override def map2[A, B, C](fa: Validation[E, A], fb: Validation[E, B])(
f: (A, B) => C
): Validation[E, C] = (fa, fb) match {
case (Success(a), Success(b)) => Success(f(a, b))
case (Failure(eh1, et1), Failure(eh2, et2)) =>
Failure(eh1, et1 ++ (eh2 +: et2))
case (Failure(eh, et), _) => Failure(eh, et)
case (_, Failure(eh, et)) => Failure(eh, et)
}
}
answer
def validationApplicative[E]: Applicative[({type f[x] = Validation[E,x]})#f] =
new Applicative[({type f[x] = Validation[E,x]})#f] {
def unit[A](a: => A) = Success(a)
override def map2[A,B,C](fa: Validation[E,A], fb: Validation[E,B])(f: (A, B) => C) =
(fa, fb) match {
case (Success(a), Success(b)) => Success(f(a, b))
case (Failure(h1, t1), Failure(h2, t2)) =>
Failure(h1, t1 ++ Vector(h2) ++ t2)
case (e@Failure(_, _), _) => e
case (_, e@Failure(_, _)) => e
}
}
@
を使ったパターンマッチが初見

Exercise 12.7
answer
We'll just work through left and right identity, but the basic idea for all these proofs is to substitute the definition of all functions, then use the monad laws to make simplifications to the applicative identities.
Let's start with left and right identity:
map2(unit(()), fa)((_,a) => a) == fa // Left identity
map2(fa, unit(()))((a,_) => a) == fa // Right identity
We'll do left identity first. We expand definition of `map2`:
def map2[A,B,C](fa: F[A], fb: F[B])(f: (A,B) => C): F[C]
flatMap(fa)(a => map(fb)(b => f(a,b)))
flatMap(unit())(u => map(fa)(a => a)) == fa
We just substituted `unit(())` and `(_,a) => a` in for `f`. `map(fa)(a => a)` is just `fa` by the functor laws, giving us:
flatMap(unit())(u => fa) == fa
Recall that `flatMap` can be rewritten using `compose`, by using `Unit` as the argument to the first function.
compose(unit, u => fa)(()) == fa
And by the monad laws:
compose(unit, f) == f
Therefore, `compose(unit, u => fa)` simplifies to `u => fa`. And `u` is just `Unit` here, and is ignored, so this is equivalent to `fa`:
(u => fa)(()) == fa
fa == fa
Right identity is symmetric; we just end up using the other identity for `compose`, that `compose(f, unit) == f`.
flatMap(fa)(a => map(unit(()))(u => a)) == fa
flatMap(fa)(a => unit(a)) == fa // via functor laws
compose(u => fa, unit)(()) == fa
(u => fa)(()) == fa
fa == fa
Associativity and naturality are left as an exercise.

Exercise 12.8
answer
def product[G[_]](G: Applicative[G]): Applicative[({type f[x] = (F[x], G[x])})#f] = {
val self = this
new Applicative[({type f[x] = (F[x], G[x])})#f] {
def unit[A](a: => A) = (self.unit(a), G.unit(a))
override def apply[A,B](fs: (F[A => B], G[A => B]))(p: (F[A], G[A])) =
(self.apply(fs._1)(p._1), G.apply(fs._2)(p._2))
}
}

Exercise 12.9
my impl
def compose[G[_]](
G: Applicative[G]
): Applicative[({ type f[x] = F[G[x]] })#f] = {
val self = this
new Applicative[({ type f[x] = F[G[x]] })#f] {
def unit[A](a: => A) = self.unit(G.unit(a))
override def apply[A, B](fab: F[G[A => B]])(fa: F[G[A]]): F[G[B]] =
self.map2(fab, fa)((gab, ga) => G.apply(gab)(ga))
}
}
answer
def compose[G[_]](G: Applicative[G]): Applicative[({type f[x] = F[G[x]]})#f] = {
val self = this
new Applicative[({type f[x] = F[G[x]]})#f] {
def unit[A](a: => A) = self.unit(G.unit(a))
override def map2[A,B,C](fga: F[G[A]], fgb: F[G[B]])(f: (A,B) => C) =
self.map2(fga, fgb)(G.map2(_,_)(f))
}
}
一つ前のproductに倣ってunitとapplyで実装したが、answerではunitとmap2の例が示されている。my implも問題ないように見える。

Exercise 12.10
answer
// If `self` and `G` both satisfy the laws, then so does the composite.
// The full proof of the laws can be found at:
// https://github.com/runarorama/sannanir/blob/master/Applicative.v

Exercise 12.11
answer
You want to try writing `flatMap` in terms of `Monad[F]` and `Monad[G]`.
def flatMap[A,B](mna: F[G[A]])(f: A => F[G[B]]): F[G[B]] =
self.flatMap(na => G.flatMap(na)(a => ???))
Here all you have is `f`, which returns an `F[G[B]]`. For it to have the appropriate type to return from the argument to `G.flatMap`, you'd need to be able to "swap" the `F` and `G` types. In other words, you'd need a _distributive law_. Such an operation is not part of the `Monad` interface.

Exercise 12.12
answer
def sequenceMap[K,V](ofa: Map[K,F[V]]): F[Map[K,V]] =
(ofa foldLeft unit(Map.empty[K,V])) { case (acc, (k, fv)) =>
map2(acc, fv)((m, v) => m + (k -> v))
}
Mapのsequenceの実装。
foldLeft(or foldRight)の初期値に単位元を渡し、map2を使って結合していく。

Exercise 12.13
answer
val listTraverse = new Traverse[List] {
override def traverse[G[_],A,B](as: List[A])(f: A => G[B])(implicit G: Applicative[G]): G[List[B]] =
as.foldRight(G.unit(List[B]()))((a, fbs) => G.map2(f(a), fbs)(_ :: _))
}
val optionTraverse = new Traverse[Option] {
override def traverse[G[_],A,B](oa: Option[A])(f: A => G[B])(implicit G: Applicative[G]): G[Option[B]] =
oa match {
case Some(a) => G.map(f(a))(Some(_))
case None => G.unit(None)
}
}
val treeTraverse = new Traverse[Tree] {
override def traverse[G[_],A,B](ta: Tree[A])(f: A => G[B])(implicit G: Applicative[G]): G[Tree[B]] =
G.map2(f(ta.head), listTraverse.traverse(ta.tail)(a => traverse(a)(f)))(Tree(_, _))
}
G: Applicative[G]
の呼び出し方がわからず戸惑ったが、implicitで与えて使えているらしい。このようなimplicitの使い方はまだ不明だが、とりあえず前に進める。

Exercise 12.14
answer
The simplest possible `Applicative` we can use is `Id`:
type Id[A] = A
We already know this forms a `Monad`, so it's also an applicative functor:
val idMonad = new Monad[Id] {
def unit[A](a: => A) = a
override def flatMap[A,B](a: A)(f: A => B): B = f(a)
}
We can now implement `map` by calling `traverse`, picking `Id` as the `Applicative`:
def map[A,B](fa: F[A])(f: A => B): F[B] =
traverse[Id, A, B](xs)(f)(idMonad)
This implementation is suggestive of laws for `traverse`, since we expect this implementation to obey the usual functor laws. See the chapter notes for discussion of the laws for `Traverse`.
Note that we can define `traverse` in terms of `sequence` and `map`, which means that a valid `Traverse` instance may define `sequence` and `map`, or just `traverse`:
trait Traverse[F[_]] extends Functor[F] {
def traverse[G[_]:Applicative,A,B](fa: F[A])(f: A => G[B]): G[F[B]] =
sequence(map(fa)(f))
def sequence[G[_]:Applicative,A](fga: F[G[A]]): G[F[A]] =
traverse(fga)(ga => ga)
def map[A,B](fa: F[A])(f: A => B): F[B] =
traverse[Id, A, B](fa)(f)(idMonad)
}

Exercise 12.15
answer
It's because `foldRight`, `foldLeft`, and `foldMap` don't give us any way of constructing a value of the foldable type. In order to `map` over a structure, you need the ability to create a new structure (such as `Nil` and `Cons` in the case of a `List`). `Traverse` is able to extend `Functor` precisely because a traversal preserves the original structure.
An example of a Foldable that is not a functor:
case class Iteration[A](a: A, f: A => A, n: Int) {
def foldMap[B](g: A => B)(M: Monoid[B]): B = {
def iterate(n: Int, b: B, c: A): B =
if (n <= 0) b else iterate(n-1, g(c), f(a))
iterate(n, M.zero, a)
}
}
This class conceptually represents a sequence of `A` values, generated by repeated function application starting from some seed value. But can you see why it's not possible to define `map` for this type?

Exercise 12.16
answer
def reverse[A](fa: F[A]): F[A] =
mapAccum(fa, toList(fa).reverse)((_, as) => (as.head, as.tail))._1
Exercise 12.17
answer
override def foldLeft[A,B](fa: F[A])(z: B)(f: (B, A) => B): B =
mapAccum(fa, z)((a, b) => ((), f(b, a)))._2

Exercise 12.18
answer
def fuse[G[_],H[_],A,B](fa: F[A])(f: A => G[B], g: A => H[B])
(implicit G: Applicative[G], H: Applicative[H]): (G[F[B]], H[F[B]]) =
traverse[({type f[x] = (G[x], H[x])})#f, A, B](fa)(a => (f(a), g(a)))(G product H)

Exrcise 12.19
answer
def compose[G[_]](implicit G: Traverse[G]): Traverse[({type f[x] = F[G[x]]})#f] =
new Traverse[({type f[x] = F[G[x]]})#f] {
override def traverse[M[_]:Applicative,A,B](fa: F[G[A]])(f: A => M[B]) =
self.traverse(fa)((ga: G[A]) => G.traverse(ga)(f))
}

Exercise 12.20
answer
def composeM[G[_],H[_]](implicit G: Monad[G], H: Monad[H], T: Traverse[H]):
Monad[({type f[x] = G[H[x]]})#f] = new Monad[({type f[x] = G[H[x]]})#f] {
def unit[A](a: => A): G[H[A]] = G.unit(H.unit(a))
override def flatMap[A,B](mna: G[H[A]])(f: A => G[H[B]]): G[H[B]] =
G.flatMap(mna)(na => G.map(T.traverse(na)(f))(H.join))
}

12章でPart Ⅲまでは終了。
終盤は難しくなぞるだけになってしまった箇所もあるが、一旦この本・分野の学習は終了(中断)。
ここまでの復習やPart Ⅳや応用分野はまた余裕ができた時にやりたい。