为什么模式匹配定义不能成为Haskell中的闭包?

时间:2014-02-17 07:54:23

标签: haskell scope pattern-matching closures

为什么不接受这些伪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

为什么我不能使用模式匹配来定义函数闭包,并使用从封闭范围获取的值?

这是因为封闭范围的值是在运行时确定的(一般情况下)由于某种原因(什么原因?)编译器无法编排它?

1 个答案:

答案 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