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

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

问题描述

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

   - 仅使用前缀记法和n + k模式(不再在Haskell 2010中允许)
阶乘0 = 1
factorial(n + 1)=(*)(n + 1)(factorial n)

n + k模式是什么意思?我想这是第二行,但我不明白这可能是错误的。任何人都可以解释那里有什么问题吗?为什么Haskell 2010中不允许使用这些n + k模式?

解决方案

什么是n + k模式?以此为准:

  $ ghci 
GHCi,版本6.12.3:http://www.haskell .org / ghc /:?寻求帮助
加载包ghc-prim ...链接...完成。
加载包integer-gmp ...链接...完成。
加载程序包库...链接...完成。
加载包ffi-1.0 ...链接...完成。
前奏>让f 0 = 0; f(n + 5)= n
前奏> :t f
f ::(Integral t)=> t - > t
前奏> f 0
0
前奏> f 1
***例外:< interactive>:1:4-24:函数中的非穷举模式f

前奏> f 2
***例外:< interactive>:1:4-24:函数中非详尽的模式f

前奏> f 3
***例外:< interactive>:1:4-24:函数中的非穷举模式f

前奏> f 4
***例外:< interactive>:1:4-24:函数中的非穷举模式f

前奏> f 5
0
前奏> f 6
1

它们在模式匹配上基本上是一个非常特殊的情况,在数字和哪些做...嗯,让我们有礼貌,并称这些数字意想不到的事情。



这里我有一个函数 f ,它有两个子句。第一个子句匹配 0 ,并且只匹配 0 。第二个子句匹配值为5或更大的Integral类型的任何值。在这种情况下,绑定名称( n )的值等于您在-5中传递的数字。至于为什么他们已从Haskell 2010中删除,我希望现在只需一点思考即可看到原因。 (提示:考虑最少突击的原则以及如何在这里适用或不适用。)




编辑补充:



现在出现一个很自然的问题,那就是你用什么来代替它们?

  $ ghci 
GHCi,版本6.12.3:http://www.haskell.org/ghc/:?寻求帮助
加载包ghc-prim ...链接...完成。
加载包integer-gmp ...链接...完成。
加载程序包库...链接...完成。
加载包ffi-1.0 ...链接...完成。
前奏>让f 0 = 0; f n | n> = 5 = n - 5
Prelude> :t f
f ::(Num t,Ord t)=> t - > t
前奏> f 0
0
前奏> f 1
***例外:< interactive>:1:4-33:函数f

中的非穷举模式前奏> f 2
***例外:< interactive>:1:4-33:函数f

中的非穷举模式前奏> f 3
***例外:< interactive>:1:4-33:函数中非详尽的模式f

前奏> f 4
***例外:< interactive>:1:4-33:函数f

中的非穷举模式前奏> f 5
0
前奏> f 6
1

您会从类型声明中注意到这些不完全相同,但是使用警卫足够平等。在表达式中使用 n-5 可能会在任何使用多个地方的代码中变得单调乏味且容易出错。答案是使用一个,其中子句符合以下内容:

 前奏>让f 0 = 0; f n | n> = 5 = n'其中,n'= n  -  5 
前奏> :t f
f ::(Num t,Ord t)=> t - > t
前奏> f 0
0
前奏> f 5
0
前奏> f 6
1

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






进一步编辑后添加:

更喜欢让表达式超过其中子句,这是一个替代方案:

 前奏>让f 0 = 0; f n |在n'
中n> = 5 =令n'= n - 5 Prelude> :t f
f ::(Num t,Ord t)=> t - > t
前奏> f 0
0
前奏> f 5
0

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


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)

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?

解决方案

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.

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.)


Edited to add:

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

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

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.


Further edited to add:

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天全站免登陆