Operators, fixity, and annotations
Operators are functions with symbolic names. Fixity declarations tell the parser how an infix expression groups; types and annotations then tell the checker what it means.
Declaring an operator
function (+++)(left:Int, right:Int) : Int = left + right;
infixl 6 (+++);Call it in either form:
1 +++ 2
(+++)(1, 2)The parenthesized name identifies the function itself.
Associativity and precedence
infixl 6 (+);
infixr 5 (++);
infix 4 (==);infixlgroups repeated uses to the left;infixrgroups to the right;infixforbids unparenthesized chaining at the same precedence.
Precedence ranges from 0 to 9; higher numbers bind more tightly. Function application and projection bind more tightly than infix operators.
Published modules should declare non-standard fixity. The interactive recovery default for an unknown operator is left-associative precedence 9, but portable source should not rely on that fallback.
Parentheses communicate intent
2 + 3 * 4
(2 + 3) * 4Fixity makes the first expression conventional; parentheses make the second grouping explicit. Add parentheses whenever mixed custom operators would make a reader reconstruct a precedence table.
Type-expression precedence
From loosest to tightest:
forallandexists;->, right associative;+;*;- type application, projection, and parentheses.
Thus A -> B -> C is A -> (B -> C), and type application binds before the arrow.
Expression annotations
value answer = (40 : Int) + 2;expression : Type checks an expression against an expected type. It helps choose overloaded literals, constructors, existential witnesses, or a higher-order argument.
An annotation does not convert the value. These are distinct operations:
x : Tchecks thatxalready has typeT;x as Tperforms an explicit declared representation conversion;downcast(T, x)performs a checked class downcast returningMaybe(T).
Prefix operators
Prefix use binds below application/projection and above infix operations. Numeric negation is the common example. Parenthesize when a prefix operator and application could be read in more than one way.
Stable numerical meaning
Operator notation does not authorize approximate rewrites. In particular, floating division must preserve the selected numerical contract, and fused multiply-add contraction is controlled artifact-wide by --fp-contract, not by operator spelling.
Common mistakes
Do not depend on the recovery fixity for a published custom operator. Remember that an annotation checks, as uses a representation mapping, and downcast checks a class relationship—these forms are not interchangeable.
Recap
Operators are ordinary functions plus declared grouping information. Parentheses remain the clearest answer when either expression or type precedence would make the intended tree uncertain.
Normative details: Language Reference §7.7, §8.4, and §4.8.