【问题标题】:Why can't pattern-matching-definition be a closure in Haskell?为什么模式匹配定义不能成为 Haskell 中的闭包?
【发布时间】:2014-03-16 10:07:52
【问题描述】:

为什么这些伪 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&lt;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

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

这是因为封闭范围的值是在运行时(通常)确定的,并且由于某种原因(什么原因?)编译器无法编排?

【问题讨论】:

  • 这是可能的,但它是一个相当脆弱的结构,根据它是否已经被绑定,在一个模式中有 n 表示不同的东西。
  • 我不确定你在问什么。 n 在您的示例中可用于g...只要您不调用gs 参数之一n

标签: haskell scope pattern-matching closures


【解决方案1】:

这是一种语言设计选择:不能对变量进行模式匹配。它避免了棘手的大脑体操来决定您是否对现有变量进行模式匹配,或者您是否声明了一个局部变量。其实看看这个例子:

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

【讨论】:

  • 在(久违的)函数式语言 ALFL(来自耶鲁大学)中,您可以说 #n 而不是 n 以表明您想要匹配变量的值而不是绑定。在 Haskell 中,你必须说 ... n' ... | n' == n。或者ViewPatterns 你可以说(True &lt;- (== n))
  • Erlang有这个问题。
猜你喜欢
  • 1970-01-01
  • 2018-08-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多