I've run into a problem I don't really understand. I thought that I would be able to write code like this in Haskell:
foo :: Maybe Int -> Int
foo Nothing = 0
foo Just x = x
But when I try to compile it, I get the error:
Equations for ‘foo’ have different numbers of arguments
I can fix it by changing my code to the following:
foo :: Maybe Int -> Int
foo Nothing = 0
foo (Just x) = x
Which makes me think that GHC is interpreting Just
as an argument to foo
. But Haskell forbids using uppercase letters to start variable names, so I wouldn't think there should be any ambiguity here. What's going on?
You're correct, there's not ambiguity about whether or not Just
is a constructor – but constructors can have no arguments! Haskell's pattern matching doesn't look up the names involved, it's strictly syntactic, and foo Just x = x
is a perfectly well-formed function definition clause. It's ill-typed:
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
but with different data types around, it'd be fine:
Prelude> data Justice = Just
Prelude> let foo Just x = x
Prelude> :t foo
foo :: Justice -> t -> t
Prelude> foo Just ()
()
Just
could be a nullary constructor (as in the second example), and since function application is left-associative, the compiler parses Just
and x
as separate arguments and you get the "different numbers of arguments" error. (And as you can see above, if there weren't the Nothing
case, you'd actually get the type error for code of that form.)
The idea is that pattern syntax should mirror application syntax. If I was calling foo
I couldn't write foo Just x
, because that means something else (and if foo
had type (Int -> Maybe Int) -> Int -> Int
then it would even work). Having patterns have different rules for where parentheses are needed than expressions would be very weird.
Writing compound patterns without parentheses and trusting the compiler to automatically group things also falls apart in more complex situations. What should this mean?
foo Just x : xs = ...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With