Open177

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

リアルにサーモンリアルにサーモン

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

リアルにサーモンリアルにサーモン

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

リアルにサーモンリアルにサーモン

3章関数型プログラミングのデータ構造

関数型データ構造は、当然ながら、純粋関数のみを使って操作されます。

datastructures/List.scala
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)

ABを継承している時にのみ、

val : G[B] = G[A]

のような代入が許される。(言い換えれば、ABの部分型である場合、G[A]G[B]の部分型となる)
sclaaではクラス定義時にclass G[+A]のように型パラメータの前に+をつけると共変として宣言される。

反変(contravariant)

共変の逆で、
ABを継承している時にのみ、

val : G[A] = G[B]

のような代入が許される。(言い換えれば、ABの部分型である場合、G[B]G[A]の部分型となる)
sclaaではクラス定義時にclass G[-A]のように型パラメータの前に-をつけると共変として宣言される。

反変が使われる主な例としては関数の型がある。

val x1: A => AnyRef = B => AnyRef型の値
x1(A型の値)

のような関数が成功するには、反変の性質を持っている必要がある。(つまりAがBの部分型である必要があり、逆は成り立たない)

https://scala-text.github.io/scala_text/type-parameter.html#変位指定(variance)

リアルにサーモンリアルにサーモン

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について
https://kmizu.hatenablog.com/entry/20091130/1259557761

scala.NothingはScalaのクラス階層における、「一番下」に位置するクラスで全ての型のサブタイプになるが

Nothingは全ての型のサブタイプであるため、どんな型の値にでも化けられるという性質がある。throw式の型をNothingとすれば、どんな型が要求されている箇所にthrow式が現れても適切に型付けされる。

全ての型のサブタイプであるNothingは、Listや上記Eitherなどの共変の型パラメータが与えられるデータ型において、どんな型にでも化けられる便利な型としてデータ構造の定義時に使われる?

https://kmizu.hatenablog.com/entry/20120810/1344601464

もう少し理解の深化が必要そう

リアルにサーモンリアルにサーモン

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キーワードを追加した変数に代入することで、宣言の右辺の評価が最初に参照される時まで先送りする性質を保ちつつ、その後の参照で評価が繰り返されないよう結果をキャッシュすることができる。

リアルにサーモンリアルにサーモン

遅延リストの定義

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に対して線形になるようにすべきである。

の条件を満たせていない?

右から畳み込んでいく中で一つ前の要素(一つ右の要素)を参照する時にキャッシュされておらず、評価が再度走ってしまう、ということか

リアルにサーモンリアルにサーモン

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.booleanState.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.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, the replicateM function will generate a list of lists. It will contain all the lists of length n with elements selected from the input list.

For Option, it will generate either Some or None based on whether the input is Some or None. The Some case will contain a list of length n that repeats the element in the input Option.

The general meaning of replicateM is described well by the implementation sequence(List.fill(n)(ma)). It repeats the ma monadic value n times and gathers the results in a single value, where the monad F 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
      }
  }

@を使ったパターンマッチが初見
https://nekogata.hatenablog.com/entry/2018/07/03/153451

リアルにサーモンリアルにサーモン

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 Ⅳや応用分野はまた余裕ができた時にやりたい。