LoginSignup

This article is a Private article. Only a writer and users who know the URL can access it.
Please change open range to public in publish setting if you want to share this article with other users.

More than 5 years have passed since last update.

Scala with Cats 4.4~4.6 Exercise & Answer

Last updated at Posted at 2018-05-21

4.4.5 What is Best: Answer

自由回答。これは少々トリッキーな問題で、答えはどんなセマンティクスを欲するか次第になる。考えるいくつかのポイントは下記:

  • エラーリカバリは大きなジョブを処理する場合に重要だ。1日分のジョブを実行し終わってから、最後の要素で失敗したことを知りたくはない。
  • エラーレポートも同様に重要だ。何かがおかしい、だけでなく、具体的に何が悪くなったのかを知る必要がある。
  • 多くの場合、最初に起きたエラーだけでなく、全てのエラーを一度に知りたいものだ。典型的な例はウェブフォームだ。ユーザーがフォームを入力した際に1つずつエラーを返すよりは、全ていっぺんに返したほうがはるかに良いUXといえる。

4.6.5 Exercise: Safer Folding using Eval: Answer

(オリジナルのfoldRightを再掲)

def foldRight[A, B](as: List[A], acc: B)(fn: (A, B) => B): B = as match {
    case head :: tail =>
      fn(head, foldRight(tail, acc)(fn))
    case Nil =>
      acc
}

最も簡単な方法は、foldRightEvalというヘルパーメソッドを定義することだ。これによりBをEval[B]で置き換え、呼び出し処理を Eval.deferで置き換えて再起呼び出しから守る。

@ def foldRightEval[A, B](as: List[A], acc: Eval[B]) (fn: (A, Eval[B]) => Eval[B]): Eval[B] = as match {
    case head :: tail =>
      Eval.defer(fn(head, foldRightEval(tail, acc)(fn)))
    case Nil =>
      acc
  }
defined function foldRightEval

foldRightをfoldRightEvalを使って再定義すれば、スタックセーフになる。

@ def foldRight[A, B](as: List[A], acc: B)(fn: (A, B) => B): B = {
    foldRightEval(as, Eval.now(acc)) {
      (a, b) => b.map(fn(a, _))
    }.value
  }
defined function foldRight

@ foldRight((1 to 100000).toList, 0L)(_ + _)
res58: Long = 5000050000L

入れ子にする形でも書ける。

@ def foldRight2[A, B](as: List[A], acc: B)(fn: (A, B) => B): B = {
    def loop[A, B](as: List[A], acc: Eval[B])(fn: (A, Eval[B]) => Eval[B]): Eval[B] =
      as match {
        case head :: tail =>
          Eval.defer(fn(head, foldRightEval(tail, acc)(fn)))
        case Nil =>
          acc
      }
    loop(as, Eval.now(acc)) { (a, b) => b.map(fn(a, _)) }.value
  }
defined function foldRight2

@ foldRight2((1 to 100000).toList, 0L)(_ + _)
res60: Long = 5000050000L
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up