在continuation中推断结果类型

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)

huy*_*hjl 2

你的问题让我想到了连续性如何跟踪状态。所以我根据你的情况进行了调整并提出了这个:

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