1

私は基本的に、ScalaAPIページで区切られた継続の例に従っています。以下のコードは正常に機能します。

import scala.util.continuations._
import scala.collection.mutable.HashMap

val sessions = new HashMap[Int, Int=>Unit]
def ask(prompt: String): Int @cps[Unit] = shift {
  ret: (Int => Unit) => {
    val id = sessions.size
    printf("%s\nrespond with: submit(0x%x, ...)\n", prompt, id)
    sessions += id -> ret
  }
}

def submit(id: Int, addend: Int): Unit = {
  sessions.get(id) match {
    case Some(continueWith) => continueWith(addend)
  }
}

def go = reset {
  println("Welcome!")
  val first = ask("Please give me a number")
  val second = ask("Please enter another number")
  printf("The sum of your numbers is: %d\n", first + second)
}

ただし、次のように変更するgoと、次のようになります。

def go = reset {
  println("Welcome!")
  List("First?","Second?").map[Int @cps[Unit]](ask)
}

このエラーが発生します:

error: wrong number of type parameters for method map: [B, That](f: String => B)
(implicit bf: scala.collection.generic.CanBuildFrom[List[String],B,That])That
             List("First?","Second?").map[Int @cps[Unit]](ask)
                                         ^

2番目のタイプのパラメーターとして追加Anyしても役に立ちません。どのタイプを提供する必要があるかについて何か考えはありますか?

4

3 に答える 3

1

mapその理由は、これは CPS 変換されたメソッドを で作成しないと単純に不可能だからListです: CPS アノテーションは、継続を必要な場所に戻すためにコンパイラにメソッドを「裏返しに」変換させ、標準List.mapは従わないからです。変換された契約。しばらくクラインの瓶に夢中になりたい場合は、ソースから生成されたクラス ファイル、特にメソッド シグネチャを参照してください。

これが、CPS プラグインがこの問題に対する完全な汎用ソリューションにならない主な理由です。これは欠陥によるものではなく、「ストレートな」コードと継続渡しスタイルとの間の固有の不一致によって引き起こされます。

于 2013-03-24T12:19:46.863 に答える
0

これが私が解決できる最も近いものです。shiftR を使用して継続をリセットするのではなく具体化し、foldRight を使用して中断された継続チェーンを構築し、shift/reset ブロックを使用して中断後に継続を取得し、「animate」メソッドを使用して中断された継続を開始します。

import scala.collection.mutable.HashMap
import scala.util.continuations._

val sessions = new HashMap[Int, (Unit=>Unit, Int)]
val map = new HashMap[Int, Int]

def ask(pair:(String, Int)) = pair match { 
  case (prompt, index) => shiftR { (ret: Unit => Unit) => {
    val id = sessions.size
    printf("%s\nrespond with: submit(0x%x, ...)\n", prompt, id)
    sessions += id -> (ret, index)
    ()
  }}
}

def submit(id: Int, addend: Int): Unit = {
  sessions.get(id) match {
    case Some((continue, index)) => { map.put(index, addend); continue() }
  }
}

def sum(m:HashMap[Int,Int]) : Int = {
  m.fold[(Int, Int)]((0, 0))((a, b) => (0, {a._2+b._2}))._2
}

type Suspended = ControlContext[Unit,Unit,Unit]

class AnimateList(l:List[Suspended]) {
  def suspend(k: => Unit) = (c: Unit) => k
  def animate(k:Unit => Unit): Unit = {
    l.foldRight(k)(
      (elem: Suspended, acc: Unit => Unit) => suspend(elem.fun(acc, ex => ())))()
  }
}

implicit def listToAnimateList(l:List[Suspended]) = new AnimateList(l)

reset { 
  val conts = List("First?","Second?","Third?").zipWithIndex.map(ask)
  shift { conts.animate }
  println(sum(map))
}
于 2013-03-26T02:46:09.503 に答える
0

暗黙的な CanBuildFrom を見つけるには、正しいパラメーターを指定する必要があります。

List("First?","Second?").map[Int @cps[Unit], List[Int @cps[Unit]](ask)

しかし、本当に型について明示する必要があるのでしょうか? 多分ちょうどうまく.map(ask)いくでしょう。

于 2013-03-23T23:34:42.000 に答える