mia*_*iah 8 continuations scala type-inference
是否可以从以下代码中删除某些类型:
import util.continuations._
object TrackingTest extends App {
implicit def trackable(x: Int) = new {
def tracked[R] = shift { cf: (Int => (R, Set[Int])) =>
cf(x) match {
case (r, ints) => (r, ints + x)
}
}
}
def track[R](body: => R @cpsParam[(R, Set[Int]), (R, Set[Int])]) = reset {
(body, Set[Int]())
}
val result = track(7.tracked[Int] + 35.tracked[Int])
assert(result == (42, Set(7, 35)))
val differentTypes = track(9.tracked[String].toString)
assert(differentTypes == ("9", Set(9)))
}
Run Code Online (Sandbox Code Playgroud)
track功能跟踪的调用tracked上的Int实例(例如7.tracked).
是否可以在tracked隐式上推断类型参数,因此以下将编译:
track(7.tracked + 35.tracked)
Run Code Online (Sandbox Code Playgroud)
你的问题让我想到了连续性如何跟踪状态。所以我根据你的情况进行了调整并提出了这个:
import util.continuations._
object TrackingTest extends App {
type State = Set[Int]
type ST = State => State
implicit class Tracked(val i: Int) extends AnyVal {
def tracked = shift{ (k: Int=>ST) => (state:State) => k(i)(state + i) }
}
def track[A](thunk: => A@cps[ST]): (A, State) = {
var result: A = null.asInstanceOf[A]
val finalSate = (reset {
result = thunk
(state:State) => state
}).apply(Set[Int]())
(result, finalSate)
}
val result = track(7.tracked + 35.tracked)
assert(result == (42, Set(7, 35)))
val differentTypes = track(9.tracked.toString)
assert(differentTypes == ("9", Set(9)))
}
Run Code Online (Sandbox Code Playgroud)
这是使用 2.10.1,但它也可以在 2.9.1 上正常工作,只要您将 2.10.x 隐式值类替换为:
implicit def tracked(i: Int) = new {
def tracked = shift{ (k: Int=>ST) => (state:State) => k(i)(state + i) }
}
Run Code Online (Sandbox Code Playgroud)
我所做的关键更改是不tracked使用任何类型推断,固定为Int@cps[ST]. 然后,CPS 插件将计算映射到String@cps[ST]适当的正确类型(例如 )。状态通过继续返回一个函数来线程化,该State=>State函数采用当前状态(整数集)并返回下一个状态。Reset 的返回类型是一个从状态到状态(类型为ST)的函数,它将采用初始状态并返回最终状态。
最后一个技巧是使用 var 捕获结果,同时仍保留 的预期类型reset。