模式匹配时参数数量不同 Maybe

Different numbers of arguments when pattern matching Maybe

我 运行 遇到了一个我不太明白的问题。我以为我可以在 Haskell:

中编写这样的代码
foo :: Maybe Int -> Int
foo Nothing = 0
foo Just x = x

但是当我尝试编译它时,出现错误:

Equations for ‘foo’ have different numbers of arguments

我可以通过将我的代码更改为以下内容来修复它:

foo :: Maybe Int -> Int
foo Nothing = 0
foo (Just x) = x

这让我觉得 GHC 正在将 Just 解释为 foo 的参数。但是 Haskell 禁止使用大写字母作为变量名的开头,所以我认为这里不应该有任何歧义。怎么回事?

你是对的,关于 Just 是否是构造函数没有歧义——但构造函数不能有参数! Haskell 的模式匹配不查找所涉及的名称,它是严格的句法,而 foo Just x = x 是一个格式良好的函数定义子句。不对-打字:

Prelude> let foo Just x = x

<interactive>:2:9:
    Constructor ‘Just’ should have 1 argument, but has been given none
    In the pattern: Just
    In an equation for ‘foo’: foo Just x = x

但是如果周围有不同的数据类型,那就没问题了:

Prelude> data Justice = Just
Prelude> let foo Just x = x
Prelude> :t foo
foo :: Justice -> t -> t
Prelude> foo Just ()
()

Just 可以是空构造函数(如第二个示例中所示),并且由于函数应用程序是左关联的,因此编译器将 Justx 解析为单独的参数,并且你得到 "different numbers of arguments" 错误。 (正如您在上面看到的,如果没有 Nothing 情况,您实际上会得到该形式代码的类型错误。)

想法是模式语法应该反映应用程序语法。如果我正在 调用 foo 我不能写 foo Just x,因为那意味着别的东西(如果 foo 有类型 (Int -> Maybe Int) -> Int -> Int那么它甚至可以工作)。对于需要括号的地方,模式与表达式有不同的规则会很奇怪。

在更复杂的情况下,编写不带括号的复合模式并相信编译器会自动对事物进行分组也会失败。这是什么意思?

foo Just x : xs = ...