什么是“n+k 模式"?为什么它们被 Haskell 2010 禁止? [英] What are "n+k patterns" and why are they banned from Haskell 2010?

查看:14
本文介绍了什么是“n+k 模式"?为什么它们被 Haskell 2010 禁止?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在阅读 维基百科关于 Haskell 2010 的条目时,我偶然发现:

When reading Wikipedia's entry on Haskell 2010 I stumbled across this:

-- 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 模式?

What do they mean by "n+k patterns"? I guess it's the second line, but I don't get what might be wrong with it. Could anyone explain what is the issue there? Why isn't these n + k patterns more allowed in Haskell 2010?

推荐答案

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

What are n+k patterns? Take a gander at this:

$ 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

它们基本上是模式匹配的一个非常特殊的例子,它只适用于数字,并且可以……好吧,让我们礼貌一点,称其为这些数字的意外事件".

They're basically an extremely special case on pattern matching which only work on numbers and which do ... well, let's just be polite and call it "unexpected things" to those numbers.

这里我有一个函数 f 它有两个子句.第一个子句匹配 0 并且只匹配 0.第二个子句匹配任何值为 5 或更大的 Integral 类型的值.绑定名称(n,在本例中)的值等于您传入的数字的负 5.至于为什么它们已从 Haskell 2010 中删除,我希望您现在可以看到原因只需要一点点思考.(提示:考虑最小意外原则"以及它在此处可能适用或不适用的情况.)

Here I have a function f which has two clauses. The first clause matches 0 and only 0. The second clause matches any value of type Integral whose value is 5 or greater. The bound name (n, in this case) has a value equal to the number you passed in minus 5. As to why they've been removed from Haskell 2010, I hope you can see the reason now with just a bit of thinking. (Hint: consider the "principle of least surprise" and how it may or may not apply here.)

编辑添加:

既然这些结构被禁止,自然会出现一个问题是你用什么来代替它们?"

A natural question to arise now that these constructs are forbidden is "what do you use to replace them?"

$ 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 子句:

You'll notice from the type statements that these are not precisely equal, but the use of a guard is "equal enough". The use of the n-5 in the expression could get tedious and error-prone in any code that uses it in more than one place. The answer would be to use a where clause along the lines of this:

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)的烦恼,但我个人觉得这是为提高认知理解而付出的小代价.

The where clause lets you use the calculated expression in multiple places without risk of mistyping. There is still the annoyance of having to edit the border value (5 in this case) in two separate locations in the function definition, but personally I feel this is a small price to pay for the increase in cognitive comprehension.

进一步编辑添加:

如果您更喜欢 let 表达式而不是 where 子句,这是一个替代方案:

If you prefer let expressions over where clauses, this is an alternative:

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

就是这样.我现在真的完成了.

And that's it. I'm really done now.

这篇关于什么是“n+k 模式"?为什么它们被 Haskell 2010 禁止?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆