Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/git/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell “中的cps”;还有另一个哈斯克尔旅行社;_Haskell - Fatal编程技术网

Haskell “中的cps”;还有另一个哈斯克尔旅行社;

Haskell “中的cps”;还有另一个哈斯克尔旅行社;,haskell,Haskell,我正在通过阅读《haskell教程》一书来学习haskell,当谈到连续传球的风格时,我遇到了一个问题。这本书给出了一个cps折叠,如: cfold’ f z [] = z cfold’ f z (x:xs) = f x z (\y -> cfold’ f y xs) 并给出了试验结果: CPS> cfold (+) 0 [1,2,3,4] 10 CPS> cfold (:) [] [1,2,3] [1,2,3] 但是,当我尝试测试时,我发现存在一个问题,ghci给出: *

我正在通过阅读《haskell教程》一书来学习haskell,当谈到连续传球的风格时,我遇到了一个问题。这本书给出了一个cps折叠,如:

cfold’ f z [] = z
cfold’ f z (x:xs) = f x z (\y -> cfold’ f y xs)
并给出了试验结果:

CPS> cfold (+) 0 [1,2,3,4]
10
CPS> cfold (:) [] [1,2,3]
[1,2,3]
但是,当我尝试测试时,我发现存在一个问题,ghci给出:

*Main> cfold (+) 0 []

<interactive>:8:7:
    Occurs check: cannot construct the infinite type:
      t10 = (t10 -> t10) -> t10
    Expected type: t10 -> t10 -> (t10 -> t10) -> t10
      Actual type: t10 -> t10 -> t10
    In the first argument of `cfold', namely `(+)'
    In the expression: cfold (+) 0 []
    In an equation for `it': it = cfold (+) 0 []
而且效果很好:

*Main> cfold (+) 0 [1,2,3]
6
所以我的问题来了,这是书中的一个bug还是我在这里错过了什么?

在另一个Haskell教程中也是对cfold的定义

此函数cfold正在使用cfold的

在WinHugs环境中,它工作正常

在另一个Haskell教程中,也是对cfold的定义

此函数cfold正在使用cfold的


在WinHugs环境中,它工作正常

我认为书中没有错误。本书中的函数
cfold'
采用连续传递样式的函数,因此传递给
cfold'
的函数必须采用3个参数:累加器、当前列表元素和要传递结果的延续

(+)
只接受两个参数,因为它不是cps样式,所以不能使用cfold函数。要使用cfold'对列表中的元素求和,可以编写:

> cfold' (\e acc cont -> cont (acc + e)) 0 [3,2,4]
9
请注意,lambda有三个参数:元素、累加器和continuation。根据当前计算的结果,延拓是一个表示“下一步要做什么”的函数。因此,通过每次调用continuation,您可以处理下一个元素

那么,如果我不调用延拓,你认为会发生什么?我是否可以停止以这种方式处理列表,以实现takeWhile之类的功能

> cfold' (\acc e cont -> if e <= 3 then cont (e : acc) else acc) [] [1,2..]
[3,2,1]
此函数仅将应用非cps函数的结果传递给continuation。您可以使用此函数实现cfold,它使用非cps样式的函数来折叠列表:

cfold :: (a -> b -> c) -> b -> [a] -> c
cfold f = cfold' (toCps2 f)
使用此功能,您现在可以使用(+)折叠列表:

> cfold (+) 0 [3,2,4]
9

我认为这本书没有错误。本书中的函数
cfold'
采用连续传递样式的函数,因此传递给
cfold'
的函数必须采用3个参数:累加器、当前列表元素和要传递结果的延续

(+)
只接受两个参数,因为它不是cps样式,所以不能使用cfold函数。要使用cfold'对列表中的元素求和,可以编写:

> cfold' (\e acc cont -> cont (acc + e)) 0 [3,2,4]
9
请注意,lambda有三个参数:元素、累加器和continuation。根据当前计算的结果,延拓是一个表示“下一步要做什么”的函数。因此,通过每次调用continuation,您可以处理下一个元素

那么,如果我不调用延拓,你认为会发生什么?我是否可以停止以这种方式处理列表,以实现takeWhile之类的功能

> cfold' (\acc e cont -> if e <= 3 then cont (e : acc) else acc) [] [1,2..]
[3,2,1]
此函数仅将应用非cps函数的结果传递给continuation。您可以使用此函数实现cfold,它使用非cps样式的函数来折叠列表:

cfold :: (a -> b -> c) -> b -> [a] -> c
cfold f = cfold' (toCps2 f)
使用此功能,您现在可以使用(+)折叠列表:

> cfold (+) 0 [3,2,4]
9