Operators in Standard ML
Learn arithmetic, comparison, logical, string, and list operators in Standard ML, including type-distinct numeric operators and function composition
Operators are how you combine values into expressions, and Standard ML’s operators reveal a lot about its character as a statically-typed functional language. Because SML uses Hindley-Milner type inference and provides no implicit conversions between numeric types, its operators are stricter than those of most dynamic languages: 1 + 1 and 1.0 + 1.0 are valid, but 1 + 1.0 is a type error.
Most SML operators are simply ordinary functions written in infix position. +, ^, and :: are values you can pass around, inspect in the REPL, and even shadow. This is consistent with SML’s functional foundation — there is little magic, just functions with infix syntax and declared precedence.
In this tutorial you’ll learn SML’s arithmetic operators (including the integer-only div and mod), comparison and logical operators, string and list operators, operator precedence, and the function composition operator o. A few things will surprise programmers coming from C-family languages: unary negation is ~ (not -), inequality is <> (not !=), and the boolean connectives andalso and orelse are keywords rather than symbols.
Arithmetic Operators
SML separates integer arithmetic from real (floating-point) arithmetic. Integers use div and mod for division and remainder; reals use /. The unary minus is the tilde ~, which is also how SML prints negative numbers.
Create a file named arithmetic.sml:
| |
Notice that Int.toString neg prints ~7: SML uses the tilde for negative literals on both input and output. Mixing types — for example 7 + 3.0 — would be rejected by the compiler, because + resolves to a single numeric type per use.
Comparison and Logical Operators
Comparison operators return a bool. Equality is = (a single equals sign) and inequality is <>. The boolean connectives are andalso and orelse, which short-circuit, plus the function not.
Create a file named comparison.sml:
| |
The = operator works only on equality types — types whose values can be compared structurally, such as int, string, char, bool, and tuples or lists of them. It does not work on real (floating-point equality is unreliable) or on functions. This restriction is enforced at compile time, which is why = on reals is a type error rather than a runtime surprise.
String and List Operators
SML has no overloaded + for strings. Instead, the dedicated ^ operator concatenates strings, and comparison operators work on strings lexicographically. Lists have their own pair of operators: :: (cons) prepends a single element, and @ (append) joins two lists.
Create a file named strings_lists.sml:
| |
The :: operator is right-associative, so 1 :: 2 :: 3 :: [] builds the list [1, 2, 3] from the right. The difference between :: and @ matters: :: takes an element and a list (int * int list), while @ takes two lists (int list * int list).
Precedence and Function Composition
Like most languages, SML gives *, div, and mod higher precedence than + and -, so multiplication happens before addition unless you add parentheses. As a functional language, SML also provides the composition operator o (a lowercase letter “o”), which builds a new function by chaining two together.
Create a file named precedence.sml:
| |
The expression double o inc reads “double after inc”: the rightmost function is applied first. So (double o inc) 5 evaluates inc 5 to 6, then double 6 to 12. Composition is a hallmark of functional programming — it lets you build pipelines of transformations without naming intermediate values.
Running with Docker
| |
Expected Output
Running arithmetic.sml:
7 + 3 = 10
7 - 3 = 4
7 * 3 = 21
7 div 3 = 2
7 mod 3 = 1
~7 = ~7
10.0 / 4.0 = 2.5
Running comparison.sml:
5 = 5 : true
5 <> 3 : true
5 < 3 : false
5 > 3 : true
5 <= 5 : true
5 >= 8 : false
true andalso false : false
true orelse false : true
not true : false
Running strings_lists.sml:
Hello, World
apple < banana : true
1, 2, 3, 4, 5
Running precedence.sml:
2 + 3 * 4 = 14
(2 + 3) * 4 = 20
double (inc 5) = 12
Key Concepts
- Numeric types are distinct: integers use
divandmod; reals use/. There is no implicit conversion, so1 + 1.0is a compile-time type error — convert explicitly withreal,floor,round, ortrunc. - Unary minus is
~, not-. SML also prints negative numbers with the tilde, so~7is both how you write and how you see a negative value. - Inequality is
<>and equality is=(a single equals sign). There is no==or!=operator in SML. =requires equality types: it works onint,string,char,bool, and structures of them, but the compiler rejects=onrealor on functions.andalsoandorelseare short-circuiting keywords, whilenotis an ordinary function of typebool -> bool.- Strings and lists have dedicated operators:
^concatenates strings,::prepends an element to a list, and@appends two lists. - Operators are functions in infix position with defined precedence —
*,div, andmodbind tighter than+and-, and the composition operatorochains functions right-to-left.
Running Today
All examples can be run using Docker:
docker pull eldesh/smlnj:latest
Comments
Loading comments...
Leave a Comment