2

私は Scala をいじっており、バイナリ ツリーの実装などの簡単な例から始めています。関数型プログラミング (OCaml、F#) の予備知識を持っていたので、バイナリ ツリー トラバーサルを末尾再帰にするために継続を使用する一般的なアプローチを再現しようとしていました。Scala の Delimited Continuations についてできる限り読んでいますが、機能させることができませんでした。

この StackOverflow questionから、この動作の OCaml 実装を読むことができます

このShift と Reset を使用したプログラミングの紹介の例に従いましたが、常に型エラーが発生し、それを機能させるために行った変更により正しい結果が得られましたが、関数の末尾を再帰的にすることはありませんでした。

これが私の実装です

abstract class IntTree
case object EmptyTree extends IntTree
case class Node( value : Int, left : IntTree, right : IntTree) extends IntTree

abstract class Result
case object Done extends Result
case class Next( n:Int, f : ( Unit => Result ) ) extends Result

def Sum(tree: IntTree): Int = {
  def walk( t : IntTree) : Unit = t match {
    case EmptyTree => ()
    case Node(v, left, right) => {
      walk(left)
      reset {
        shift { k: (Unit => Result) => Next(v, k) }
        walk(right)
      }
    }
  }
  def start( t : IntTree) = { walk(t); Done }
  def sumResult( ls : Result, acc : Int) : Int = ls match {
    case Done => acc
    case Next(value, k) => {
      sumResult(k(), acc + value)
    }
  }


  sumResult( start(tree), 0 )
}

また、区切り継続がこの仕事に適したツールであるかどうかも疑問に思っています。この問題は明示的なスタックを渡すことで効率的に解決できることはわかっていますが、Scala で cps を使用する方法を理解したいと思います。

4

0 に答える 0