dev*_*ium 60 haskell functional-programming
在阅读维基百科在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)
Run Code Online (Sandbox Code Playgroud)
"n + k模式"是什么意思?我想这是第二行,但我不知道它可能有什么问题.任何人都可以解释那里的问题是什么?为什么Haskell 2010中不允许使用这些n + k模式?
JUS*_*ION 62
什么是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
Run Code Online (Sandbox Code Playgroud)
它们基本上是一个非常特殊的模式匹配案例,它只对数字起作用,而且......它们只是礼貌并称之为"意想不到的事物".
这里我有一个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
Run Code Online (Sandbox Code Playgroud)
你会从类型陈述中注意到这些并不完全相同,但是使用一个后卫"足够相同".使用的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
Run Code Online (Sandbox Code Playgroud)
该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
Run Code Online (Sandbox Code Playgroud)
就是这样.我现在真的完成了.
归档时间: |
|
查看次数: |
8219 次 |
最近记录: |