为什么不接受这些伪Haskell函数定义?
f n = if n<3 then n else g 2 2 1 0 where
g n a b c = a -- note that 'n' is a value of the enclosing scope
g k a b c = g (k+1) (a+2*b+3*c) a b
计算这个“运动功能”:f(n) = n if n<3 else f(n-1) + 2*f(n-2) + 3*f(n-3)
fib n = let
f n a b = b -- note that 'n' is a value of the enclosing scope
f k a b = f (k+1) b (a+b)
in f 1 0 1
用于计算斐波纳契数。当然这有效:
fib n = let { f k a b = if k==n then b else f (k+1) b (a+b);} in f 1 0 1
但是在where
的示例和let
的示例中,我得到了
Warning: Pattern match(es) are overlapped
为什么我不能使用模式匹配来定义函数闭包,并使用从封闭范围获取的值?
这是因为封闭范围的值是在运行时确定的(一般情况下)由于某种原因(什么原因?)编译器无法编排它?
答案 0 :(得分:9)
这是一种语言设计选择:无法对变量进行模式匹配。它可以避免棘手的大脑体操来决定你是否与现有变量进行模式匹配,或者你是否声明了一个局部变量。实际上,看一下这个例子:
Foo.hs:
module Foo where
foo: Int = 42
Bar.hs:
module Bar where
import Foo
bar :: Int -> Bool
bar foo = True
bar _ = False
通过查看Bar.hs,您无法轻易猜出foo
受到约束。拥有一个语法,其中需要上下文来决定是否声明一个新变量或使用现有变量是误导。
作为一种解决方法,您仍然可以使用警卫:
f n = if n<3 then n else g 2 2 1 0 where
g k a _ _ | k == n = a
g k a b c = g (k+1) (a+2*b+3*c) a b
或
f n = if n<3 then n else g 2 2 1 0 where
g k a b c | k == n = a
| otherwise = g (k+1) (a+2*b+3*c) a b