Haskell “中的cps”;还有另一个哈斯克尔旅行社;
我正在通过阅读《haskell教程》一书来学习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给出: *
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