Haskell:以连续传递方式完全定义阶乘的问题

Haskell:以连续传递方式完全定义阶乘的问题,haskell,continuations,factorial,Haskell,Continuations,Factorial,我一直试图在一个大的blob中理解函数式编程、Haskell和Continuation-Passing风格,而我的结构化/OOP背景让我很难理解 据我所知,以下是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)”部分是否正确?它不太正确(并且不适合我编译);值n+1

我一直试图在一个大的blob中理解函数式编程、Haskell和Continuation-Passing风格,而我的结构化/OOP背景让我很难理解

据我所知,以下是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)”部分是否正确?

它不太正确(并且不适合我编译);值
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模式”,默认情况下,IIRC在GHC中不再可用。您可以使用普通模式变量,而不是“n+k模式”。注意,我对基本情况使用了
1
;如果您从
n
开始倒计时,这一点更容易解释,并且应该在计算中的每个步骤应用continuation函数(您从归纳步骤中删除了它)。记住这些,你就可以写作了

factorial n' = fact n' id
 where
  fact 0 cont = cont 1
  fact n cont = fact (n-1) (cont . (* n))
<>我会或多或少地考虑这个问题。

编辑:我个人不喜欢n+k模式,但我想我应该花点时间来解释它们。我发现,如果你想用一个基本情况和一个归纳步骤来进行数学归纳,你会更容易理解。基本情况是
事实0…
。然后从基本步骤开始定义其他值:“对于任何
事实n k
,通过此关系确定
事实(n+1)k
。”这与我对正常模式变量的看法不同,即自上而下,而不是像这里那样自下而上,但我认为这解释了动机以及一些人喜欢这种风格的原因


我不喜欢n+k模式的原因很简单,因为我发现定义比较混乱,但YMMV。

谢谢你,John-讽刺的是,我刚刚在发现Haskell程序员的进化,这也表明“n+k”模式是个坏主意。Haskell 2010删除了(n+k)模式语法。您对
fact
的定义中的
n
n
隐藏在
factorial n
中,这不利于清晰。原来的问题也是如此。@Nefrubyr-非常感谢;我已经编辑了这些以移除阴影。