什么是 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。第二个子句匹配任何值为 5 或更大的 Integral 类型的值。绑定的名称(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
您会从类型语句中注意到它们并不完全相等,但使用保护是“足够相等的”。在表达式中使用 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
where 子句允许您在多个位置使用计算表达式,而不会出现输入错误的风险。在函数定义的两个不同位置编辑边框值(在本例中为 5)仍然很烦人,但我个人认为这是为提高认知理解付出的不小的代价。
进一步编辑添加:
如果您更喜欢 let 表达式而不是 where 子句,这是一种替代方法:
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
就是这样。我现在真的完成了。