中缀值构造函数固定性问题:Haskell中Some构造函数调用差异原因
Hey there! Let's unpack this behavior step by step—it all boils down to Haskell's rules for function/constructor application and operator fixity.
Why the three expressions act differently
Let's break each case down:
1. Some (id 1) (id 2) works as expected
When you use a constructor (or any function) in prefix form, it expects exactly the number of arguments it's defined for—here, Some takes two. The parentheses make it explicit that we're passing id 1 (which evaluates to 1) as the first argument, and id 2 (which evaluates to 2) as the second. Haskell parses this exactly how you intend, resulting in Some 1 2.
2. Some id 1 id 2 throws a type error
Haskell's function/constructor application has the highest possible precedence, and it's left-associative. That means this line gets parsed like this:
(((Some id) 1) id) 2
Let's walk through this:
- First,
Some idcreates a partial function (thanks to Haskell's currying) that needs one more argument to make a fullSomevalue. - Then
Some id 1completes the constructor call, producing aSome id 1value (typeSome (a -> a) Integer). - Now we try to apply this
Somevalue toid—butSome id 1is a data value, not a function! That's why you get the type mismatch error: the compiler expects a function that can takeidand2as arguments, but you're feeding it a concreteSomevalue instead.
3. id 1 Some id 2 works like the first case
Wrapping a constructor (or function) in backticks turns it into an infix operator. Infix operators have lower precedence than regular function application—so Haskell will first evaluate the operands on either side:
id 1becomes1id 2becomes2
Then it applies the infixSometo these two results, which is exactly equivalent toSome (id 1) (id 2). Hence, you getSome 1 2.
Is the default fixity of infix data constructors the lowest?
Short answer: No, it's actually the highest possible.
In Haskell, any user-defined infix operator (including data constructors used in infix form) has a default fixity of infixl 9—precedence levels range from 0 (lowest) to 9 (highest).
Wait, but why does id 1 Some id 2 work then? Because regular function application always has higher precedence than any operator, no matter the operator's fixity. So calls like id 1 will always be evaluated before the infix operator is applied, regardless of how high the operator's precedence is.
For example, even if you explicitly declared Some with a lower precedence (like infixl 3 Some``), id 1 Some id 2 would still first compute id 1 and id 2—function application always wins.
To clarify: Fixity only determines how operators of different precedence are grouped when used together (e.g., a + b * c groups as a + (b * c) because * has higher precedence than +). It doesn't override the fact that function application is the highest-priority operation in Haskell.
内容的提问来源于stack exchange,提问作者Siegmeyer

