Scalaリスト遊び2(Scala関数型デザインより)

Scalaのリスト遊びの続き。

  def reverse[A](l: List[A]): List[A] = 
    foldLeft(l)(List[A]())((acc:List[A],h:A) => Cons(h,acc))

引数で指定されたリストを逆にする。

  def reverse[A](l: List[A]): List[A] = 
    foldLeft(l)(List[A]())((acc:List[A],h:A) => Cons(h,acc))

引数で指定されたリストを逆にする。

  def foldRight2[A,B](l: List[A])(z: B)(f: (A, B) => B): B =
    foldLeft(reverse(l))(z)((b,a) => f(a,b))

foldRightをfoldLeftを使って、実装する。 * reverseを使って、リストを逆にして、畳込み関数の引数も逆にして、実行する。

  def append2[A](l: List[A], r: List[A]): List[A] = 
    foldRight(l)(r)(Cons(_,_))
  def append3[A](a1: List[A], a2: List[A]): List[A] = 
    foldLeft(reverse(a1))(a2)((acc,h) => Cons(h,acc))

foldRightとfoldLeftを使ったappendの再実装。 * foldRightを使った方が素直。アキュムレータの初期値のrリストに対して、lのリストを右から読んでいって、Consでつなげていけばよい。 * Consの定義がCons+Aのため、このような形になる。

  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)

foldRightをfoldLeftを使って、実装する。 の別解。難しい。 * アキュムレータの初期値((b:B) => b)を関数にして、畳込み計算中には、実行させない。のと関数合成((g,a) => b => g(f(a,b)))を作って、初期値(z)を適用させているらしい。 codeday.me

以下は、appendの実行例。

    val l = List(1,2,3,4,5)
    println(s"l:${l}")
    val l2 = List(6,7,8)
    println(s"l2:${l2}")

    val result = append2(l,l2)
    println(s"result:${result}")

    val result2 = append3(l,l2)
    println(s"result2:${result2}")