代码之家  ›  专栏  ›  技术社区  ›  devoured elysium

什么是“n+k模式”以及为什么它们在Haskell 2010中被禁止?

  •  57
  • devoured elysium  · 技术社区  · 14 年前

    Wikipedia's entry on Haskell 2010 我偶然发现:

    -- using only prefix notation and n+k-patterns (no longer allowed in Haskell 2010)
    factorial 0 = 1
    factorial (n+1) = (*) (n+1) (factorial n)
    

    “n+k模式”是什么意思?我想这是第二条线,但我不知道它有什么问题。有人能解释一下问题是什么吗?为什么在Haskell 2010中不允许使用这些n+k模式?

    2 回复  |  直到 8 年前
        1
  •  66
  •   JUST MY correct OPINION    14 年前

    什么是n+k模式?看看这个:

    $ ghci
    GHCi, version 6.12.3: http://www.haskell.org/ghc/  :? for help
    Loading package ghc-prim ... linking ... done.
    Loading package integer-gmp ... linking ... done.
    Loading package base ... linking ... done.
    Loading package ffi-1.0 ... linking ... done.
    Prelude> let f 0 = 0 ; f (n+5) = n
    Prelude> :t f
    f :: (Integral t) => t -> t
    Prelude> f 0
    0
    Prelude> f 1
    *** Exception: <interactive>:1:4-24: Non-exhaustive patterns in function f
    
    Prelude> f 2
    *** Exception: <interactive>:1:4-24: Non-exhaustive patterns in function f
    
    Prelude> f 3
    *** Exception: <interactive>:1:4-24: Non-exhaustive patterns in function f
    
    Prelude> f 4
    *** Exception: <interactive>:1:4-24: Non-exhaustive patterns in function f
    
    Prelude> f 5
    0
    Prelude> f 6
    1
    

    它们基本上是模式匹配的一个非常特殊的例子,它只对数字起作用,而对。。。好吧,让我们礼貌一点,把这些数字称为“意想不到的事情”。

    f 它有两个子句。第一个子句匹配 0 而且只有 0 n ,在本例中)的值等于传入的数字减5。至于为什么他们已经从Haskell 2010中删除了,我希望你现在只要想一想就能明白原因。(提示:考虑一下“最小惊喜原则”以及它在这里的适用与否。)


    编辑以添加:

    现在出现的一个自然问题是,这些构造被禁止了,“你用什么来替换它们?”

    $ ghci
    GHCi, version 6.12.3: http://www.haskell.org/ghc/  :? for help
    Loading package ghc-prim ... linking ... done.
    Loading package integer-gmp ... linking ... done.
    Loading package base ... linking ... done.
    Loading package ffi-1.0 ... linking ... done.
    Prelude> let f 0 = 0 ; f n | n >= 5 = n - 5
    Prelude> :t f
    f :: (Num t, Ord t) => t -> t
    Prelude> f 0
    0
    Prelude> f 1
    *** Exception: <interactive>:1:4-33: Non-exhaustive patterns in function f
    
    Prelude> f 2
    *** Exception: <interactive>:1:4-33: Non-exhaustive patterns in function f
    
    Prelude> f 3
    *** Exception: <interactive>:1:4-33: Non-exhaustive patterns in function f
    
    Prelude> f 4
    *** Exception: <interactive>:1:4-33: Non-exhaustive patterns in function f
    
    Prelude> f 5
    0
    Prelude> f 6
    1
    

    您将从type语句中注意到,这些并不完全相等,但是使用一个保护是“足够相等的”。使用 n-5 在表达式中,任何在多个地方使用它的代码都可能会变得单调乏味且容易出错。答案是使用 where 条款大意如下:

    Prelude> let f 0 = 0 ; f n | n >= 5 = n' where n' = n - 5
    Prelude> :t f
    f :: (Num t, Ord t) => t -> t
    Prelude> f 0
    0
    Prelude> f 5
    0
    Prelude> f 6
    1
    

    哪里 子句允许您在多个位置使用计算的表达式,而不存在键入错误的风险。在函数定义的两个不同位置编辑边界值(在本例中为5)仍然是一个烦恼,但我个人认为这是认知理解能力提高的一个小代价。


    let 表达式结束 哪里 条款,这是另一种选择:

    Prelude> let f 0 = 0 ; f n | n >= 5 = let n' = n - 5 in n'
    Prelude> :t f
    f :: (Num t, Ord t) => t -> t
    Prelude> f 0
    0
    Prelude> f 5
    0
    

    就这样。我现在真的受够了。

        2
  •  4
  •   perimosocordiae    14 年前

    trinithis提供的链接是正确的;n+k模式不再包含在Haskell规范中。

    有关一般n+k模式的更多背景信息,请在上向下滚动约3/5页 pattern matching ,或者看看这条短裤 post