什么是“n + k模式”,为什么他们从Haskell 2010被禁止?

当阅读维基百科在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模式?

什么是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> :tf 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 。 第二个子句匹配任何值为5或更大的Integraltypes的值。 绑定的名字(在本例中是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 ; fn | n >= 5 = n - 5 Prelude> :tf 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 

你会从types声明中注意到这些并不完全相等,但是使用警卫是“足够平等的”。 在expression式中使用n-5可能会在任何使用多个地方的代码中变得繁琐和容易出错。 答案将是沿着这条线使用where子句:

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

where子句允许您在多个地方使用计算的expression式,而不会产生input错误。 在函数定义中的两个不同的位置上,仍然不得不编辑边界值(在这种情况下是5)的烦恼,但是我个人认为这对于增加认知理解来说是一个小的代价。


进一步编辑添加:

如果你喜欢letexpression式在where子句,这是一个替代:

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

就是这样。 我现在真的做完了

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

有关n + k模式的更多背景知识,请在模式匹配上滚动本页面的3/5,或查看此短文。