You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

中缀值构造函数固定性问题: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 id creates a partial function (thanks to Haskell's currying) that needs one more argument to make a full Some value.
  • Then Some id 1 completes the constructor call, producing a Some id 1 value (type Some (a -> a) Integer).
  • Now we try to apply this Some value to id—but Some id 1 is a data value, not a function! That's why you get the type mismatch error: the compiler expects a function that can take id and 2 as arguments, but you're feeding it a concrete Some value 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 1 becomes 1
  • id 2 becomes 2
    Then it applies the infix Some to these two results, which is exactly equivalent to Some (id 1) (id 2). Hence, you get Some 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:38:57