我遇到了一个我不太懂的问题。我以为我可以在Haskell中编写这样的代码:
foo :: Maybe Int -> Int
foo Nothing = 0
foo Just x = x
但是当我尝试编译它时,我收到错误:
'foo'的等式具有不同数量的参数
我可以通过将我的代码更改为以下内容来修复它:
foo :: Maybe Int -> Int
foo Nothing = 0
foo (Just x) = x
这使我认为GHC将Just
解释为foo
的参数。但是Haskell禁止使用大写字母来启动变量名,所以我不认为这里应该有任何歧义。发生了什么事?
答案 0 :(得分:11)
你是对的,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
可能是一个无效的构造函数(如第二个示例中所示),并且由于函数应用程序是左关联的,因此编译器会将Just
和x
解析为单独的参数,并且“不同数量的论点”错误。 (正如您在上面所看到的,如果没有Nothing
的情况,您实际上会得到该表单代码的类型错误。)
答案 1 :(得分:4)
我们的想法是模式语法应该反映应用程序语法。如果我正在调用 foo
我无法写foo Just x
,因为这意味着其他内容(如果foo
的类型为(Int -> Maybe Int) -> Int -> Int
,则会甚至工作)。模式对于需要括号的地方有不同的规则,而表达式则非常奇怪。
在没有括号的情况下编写复合模式并信任编译器以自动分组事物在更复杂的情况下也会崩溃。这应该是什么意思?
foo Just x : xs = ...