是否“重置”?需要“转移”在块内?

发布于 2024-11-07 15:35:55 字数 364 浏览 4 评论 0原文

reset 需要块内的 shift 是否正确?我尝试了一下并得到以下结果:

scala> reset {} 
error: cannot cps-transform expression (): type arguments [Unit,Unit,Nothing]
do not conform to method shiftUnit's type parameter bounds [A,B,C >: B]

它看起来合理(因为内部没有 shiftreset 块是“死代码”,永远不会执行)但我不明白该错误。

错误消息的确切含义是什么?

Is it correct that reset requires shift inside the block? I tried it and got the following:

scala> reset {} 
error: cannot cps-transform expression (): type arguments [Unit,Unit,Nothing]
do not conform to method shiftUnit's type parameter bounds [A,B,C >: B]

It looks reasonable (since reset block without shift inside is "dead code", which is never executed) but I do not understand the error.

What is the exact meaning of the error message?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

夜吻♂芭芘 2024-11-14 15:35:55

我不同意,如果没有 shiftreset 中的代码就死了。实际上 reset 只是定义了延续的边界(那是因为它们被称为分隔延续)。如果你在某个地方有shift,代码就会死掉在 reset 内并且您不调用延续函数。例如:

reset {
  println(1)
  shift((k: Unit => Unit) => println(2))
  println(3)
}

shift之后的代码是死的(println(3)),因为我没有调用k(Unit)

另一方面,似乎 reset 期望从它的主体中得到一些特殊的返回类型 - 使用 @cpsParam 注释进行注释的类型。您可以检查 reset 方法的定义:

def reset[A,C](ctx: => (A @cpsParam[A,C])): C = ...

并且 shift 产生的正是 reset 方法所期望的。以下是 shift 方法的定义:

def shift[A,B,C](fun: (A => B) => C): A @cpsParam[B,C] = ...

但是您仍然可以使用 reset 而无需在其中调用 shift 。这个技巧可以做到这一点:

def foo[T](body: => T @cps[Any]) = reset(body)

foo {
  println("it works")
}

请注意,@cps 只是 @cpsParam 的类型别名。这是它的定义:

type cps[A] = cpsParam[A, A]

I don't agree, that code within reset is dead without shift. Actually reset just defines the boundaries of a continuation (that's because they are called delimited continuations).The code would be dead if you have shift somewhere within reset and you do not call continuation function. For example:

reset {
  println(1)
  shift((k: Unit => Unit) => println(2))
  println(3)
}

The code after shift is dead (println(3)) because I have not called k(Unit).

From the other hand, seems that reset expects some special return type from it's body - the one that annotated with @cpsParam annotation. You can check definition of reset method:

def reset[A,C](ctx: => (A @cpsParam[A,C])): C = ...

And shift produces just what reset method expects. Here is definition of shift method:

def shift[A,B,C](fun: (A => B) => C): A @cpsParam[B,C] = ...

But you still can use reset without shift call within it. This trick will do it:

def foo[T](body: => T @cps[Any]) = reset(body)

foo {
  println("it works")
}

Please note, that @cps is just type alias for @cpsParam. Here it's definition:

type cps[A] = cpsParam[A, A]
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文