1

我基本上遵循Scala API 页面上给出的用于分隔延续的示例。下面的代码工作正常:

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)
                                         ^

添加Any为第二种类型参数没有帮助。知道我应该提供什么类型吗?

4

3 回答 3

1

map原因是,如果不创建 CPS 转换的方法,这是不可能的List:CPS 注释使编译器将您的方法“从里到外”,以便将延续传递回需要的地方,并且标准List.map不遵守转换的合同。如果您想暂时将自己的思想包裹在克莱因瓶中,您可以查看从您的源代码生成的类文件,特别是方法签名。

这就是为什么 CPS 插件永远不会成为这个问题的完整通用解决方案的主要原因,这不是由于缺陷,而是由于“直接”代码和延续传递风格之间的固有不匹配造成的。

于 2013-03-24T12:19:46.863 回答
0

您需要为要找到的 CanBuildFrom 隐式提供正确的参数:

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

但是你真的需要明确类型吗?也许只是做.map(ask)会工作。

于 2013-03-23T23:34:42.000 回答
0

这是我能解决的最接近的事情。它使用 shiftR 来具体化延续而不是重置它,使用 foldRight 构造暂停的延续链,使用 shift/reset 块来获取暂停后的延续,并使用“动画”方法来启动暂停的延续。

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 回答