【问题标题】:Haskell: problems fully defining factorial in Continuation Passing StyleHaskell:在延续传递风格中完全定义阶乘的问题
【发布时间】:2011-01-23 12:15:08
【问题描述】:

我一直在尝试将函数式编程、Haskell 和延续传递风格理解为一个大项目,而我的结构化/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)”部分是否正确?

【问题讨论】:

    标签: haskell continuations factorial


    【解决方案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 开始倒计时,这更容易推理,并且应该在计算中的每个步骤应用延续函数(您已将其从归纳步骤中删除)。考虑到这些,你可以写

    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。

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-06-30
    • 2012-04-19
    • 1970-01-01
    • 1970-01-01
    • 2021-12-26
    • 2010-12-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多