【问题标题】:Haskell, Simple ContinuationHaskell,简单延续
【发布时间】:2014-12-06 06:16:22
【问题描述】:

我很难转换一个简单的 CPS 函数

这是一个 CPS 风格的平方函数

-- from : http://en.wikibooks.org/wiki/Haskell/Continuation_passing_style
square :: Int -> Int
square x = x * x

square_cps :: Int -> ((Int -> r) -> r)
square_cps = \cont -> cont (square x)
-- square_cps 3 print will write '9' out in console

现在,我想以相反的顺序更改函数参数

square_cps' :: ((Int -> r) -> r) -> Int
square_cps' = ?

不可能吗?

【问题讨论】:

    标签: haskell continuations


    【解决方案1】:

    首先对square_cps 的定义稍作修正:

    square_cps :: Int -> ((Int -> r) -> r)
    square_cps x = \cont -> cont (square x)
              ^^^
    

    或者你可以写:

    square_cps x cont = cont (square x)
    

    请注意,即使类型签名使 square_cps 看起来像只有一个参数的函数,这仍然有效。

    现在,square_cps' 的类型签名无法工作。他们的写法意味着您可以从(Int -> r) -> r 中获得Int,这是一个返回r 的函数。

    要将参数翻转为square_cps,首先编写这个等效的类型签名:

    square_cps :: Int -> (Int -> r) -> r
                  ^      ^             ^--- result
                  |       \--- second arg
                  \--- first arg
    

    并确定参数,如图所示。然后交换第一个和第二个参数会产生这个签名:

    square_cps' :: (Int -> r) -> Int -> r
    square_cps' cont x = square_cps x cont
    

    一般情况下,签名a -> b -> c等价于a -> (b -> c),即函数类型构造函数关联到右边。

    【讨论】:

    • 谢谢!现在我明白为什么它不起作用了。但是 'square_cps x cont = cont (square x)' 对我来说仍然模棱两可。它接受签名中描述的所有类型并返回r。这意味着, foo :: Int -> Int 可以像 foo x y = x + y 那样实现。因为 foo 也接受所有参数并返回 Int。但这给了我编译器错误。
    • 当您定义:foo x y = x + y,那么foo 的类型为Int -> Int -> Int,而不是Int -> Int。请参阅these answers 了解如何使用 ghci 打印表达式的类型。
    猜你喜欢
    • 2015-09-30
    • 1970-01-01
    • 2010-10-14
    • 1970-01-01
    • 1970-01-01
    • 2011-02-09
    • 1970-01-01
    • 2023-02-26
    • 1970-01-01
    相关资源
    最近更新 更多