前回のエントリの続き。
演習問題を解いていきます。
第1章はざっと読み進めて、さっさと演習問題が始まる第2章へ進みましょう(コーヒーの支払いのところとか若干???みたいな感じもあるし)。
第2章 Scala関数型プログラミングの準備
第2章も前半はScalaの言語仕様の解説なので、ざっと読み進めていけばよく、「2.6 型に従う実装」あたりから段々と本書らしい内容になっていきます。
早速実装を始めていきます。
実装の前に、必ずEXERCISEの番号をコメントで追加しておくと後から見返しやすくなります。
object PolymorphicFunctions: // EXERCISE 2.3 def curry[A,B,C](f: (A, B) => C): A => (B => C) = ??? end PolymorphicFunctions
テストコードも用意します。EXERCISE 2.3のお題であるcurry
は、標準ライブラリにも同様の仕様であるcurried
というメソッドが用意されているので、テストにもそちらを使ってみましょう。
package fpinscala.gettingstarted import wvlet.airspec.* class GettingStartedSpec extends AirSpec: // EXERCISE 2.3 test("curry") { val f = (a: Int, b: Double) => a.toString + " & " + b.toString PolymorphicFunctions.curry(f)(42)(4.2) shouldBe f.curried(42)(4.2) } end GettingStartedSpec
続くEXERCISE 2.4のuncurried
に該当するメソッドは用意されていませんが、curried
を適用した結果にuncurried
を適用すれば元の関数に戻るはずです。
uncurry
の型シグニチャ
// EXERCISE 2.4 def uncurry[A,B,C](f: A => B => C): (A, B) => C = ???
テストコード
// EXERCISE 2.4 test("uncurry") { val f = (a: Int, b: Double) => a.toString + " & " + b.toString PolymorphicFunctions.uncurry(f.curried)(42, 4.2) shouldBe f(42, 4.2) }
EXERCISE 2.5のcompose
は、標準ライブラリに同名のcompose
が用意されています。
composeの型シグニチャ
// EXERCISE 2.5 def compose[A,B,C](f: B => C, g: A => B): A => C = ???
テストコード
// EXERCISE 2.5 test("compose") { val g = (a: Int) => a.toString val f = (b: String) => "The answer is " + b PolymorphicFunctions.compose(f, g)(42) shouldBe (f compose g)(42)
なお、カリー化や、関数の合成の解説は英語版のWikipediaが充実しています(FP in ScalaのWikiにもリンクが貼られています)。
Function composition - Wikipedia
おわりに
次は第3章へ進みます。