我一直试图在一个大blob中强调功能编程,Haskell和Continuation Passing Style,而我的结构化/ OOP背景让我很难过。
根据this我理解以下内容应该是CPS风格中阶乘的正确定义:
factorial n = fact n id where id = \x -> x
fact 0 cont = cont n
fact (n+1) cont = fact n * (n + 1)
但我不确定最后的“*(n + 1)”部分 - 这是正确的吗?
答案 0 :(得分:6)
这不太正确(并且不为我编译);值n+1
是正确的,但它没有以完全正确的方式使用。也许您打算使用操作员部分?
factorial n' = fact n' id
where
id = \x -> x
fact 0 cont = cont 1
fact (n+1) cont = fact n (cont . (* (n+1)))
这与以下
相同(但比以上更钝)factorial n' = fact n' id
where
id = \x -> x
fact 0 cont = cont 1
fact (n+1) cont = fact n (\ret -> cont (ret * (n+1)) )
我会在这里改变一些事情。首先,id
是标准函数,因此您无需重新定义它。其次,这些示例使用“n + k模式”,在GHC中默认不再提供IIRC。您可以使用普通模式变量代替“n + k模式”。请注意,我使用1
作为基本情况;如果你从n
开始倒计时,这更容易推理,并且应该在计算中的每一步应用延续函数(你已经从归纳步骤中删除了它)。考虑到这些,你可以写
factorial n' = fact n' id
where
fact 0 cont = cont 1
fact n cont = fact (n-1) (cont . (* n))
我会考虑或多或少地习惯。
编辑:我个人不喜欢n + k模式,但我想我会花一些时间来解释它们。如果您考虑使用基础案例和归纳步骤进行数学归纳,我会发现更容易理解。基本案例是fact 0 ...
。然后,您可以从基本步骤继续定义其他值:“对于任何fact n k
,请通过此关系确定fact (n+1) k
。”这与我对正常模式变量的看法不同,这是自上而下而不是自下而上,但我认为它解释了动机以及为什么有些人喜欢这种风格。
我不喜欢n + k模式的原因仅仅是因为我发现定义更混乱,但是YMMV。