CPS转换[Scala]

时间:2018-06-26 11:26:41

标签: scala continuations continuation-passing

我正在尝试使用我在其他语言中在线找到的示例将一些功能转换为Scala中的CPS。

我们只有一个关于CPS的讲座,所有内容都应该是非常基础的,但我仍然不太了解如何正确进行转换。

这些是我在Scala上尝试在网上找到的示例。

pow2' :: Float -> (Float -> a) -> a
pow2' a cont = cont (a ** 2)

add' :: Float -> Float -> (Float -> a) -> a
add' a b cont = cont (a + b)

sqrt' :: Float -> ((Float -> a) -> a)
sqrt' a = \cont -> cont (sqrt a)

pyth' :: Float -> Float -> (Float -> a) -> a
pyth' a b cont = pow2' a (\a2 -> pow2' b (\b2 -> add' a2 b2 (\anb -> sqrt' anb cont)))

现在我开始做pow2',看起来像这样:

def pow2_k(a:Float, k:(Float => Float)) : Float =
    (a*a)

def pow2_cont(n: Float) = pow2_k(n, (x: Float) => x)

起初我有k(a*a)而不是简单的(a*a),这导致了奇怪的结果。

接下来,我尝试添加”,目前看起来像这样:

def add_k(a:Float, b:Float, k:(Float, Float => Float)) : Float =
    (a+b)

def add_k_cont(n:Float,m:Float) = add_k(n,m (x: Float, y:Float => (n+m)))

这显然是错误的。我在编写正确的续篇时遇到麻烦。 有谁知道一个很好的网站,论文,视频等来说明CPS的转换和延续?我发现的大多数工具要么太短,没有示例,要么太复杂。我觉得对于这些我要转换的简单函数来说,并没有那么复杂...

谢谢。

1 个答案:

答案 0 :(得分:1)

def pow2_k[A](f: Float, k: Float => A): A = k(f * f)

def pow2_cont(n: Float): Float = pow2_k(n, identity)

scala> pow2_cont(2.0f)
res0: Float = 4.0

scala> pow2_k(4.0f, println)
16.0

想象CPS转换的最简单方法可能是:

  • 采用不在CPS中的功能

    def square(f: Float): Float = f * f
    
  • 使函数具有类型A的泛型;将函数的第二个参数从旧函数的结果类型添加到A中;并将函数的结果类型更改为A

    def cpsSquare[A](f: Float, ret: Float => A): A = ???
    
  • 在每个函数“返回”一个值的地方(当然请注意,Scala中的return具有奇异的语义,因此return确实是一种不好的代码味道),请传递该值返回到函数(我称这个函数ret暗示发生了什么事)

    def cpsSquare[A](f: Float, ret: Float => A): A = ret(f * f)
    

基本上,在CPS中,您无需返回值,而是使用要返回的值调用传递的函数(延续)。