Types may be recursive, making it easy to define recursive data structures like lists or trees. For example, a list of 'as could be defined using two cases:
eol: an ‘end of list’ markernil'a, followed by the rest of the list of 'as, which may be empty
+: of 'a * 'a list::A binary tree could be defined as two cases as well:
leafnode, containing an item of type 'a and two subtrees, left and rightUser-defined operators, like +: used here, may be made usable infix, that is, between two arguments, by using the infixr <N> op and infix <N> op keywords. Taking subtraction as an example, e.g., 3 - 4 - 5 - 6:
infixr, it would try to parse it as (3 - (4 - (5 - 6))) = ~2infix, so it actually parses as (((3 - 4) - 5) - 6) = ~12<N> specifies how tightly operators bind to their arguments. Given two operators, * and -, and the expression 3 * 4 - 5:
infix 3 *, infix 4 - would parse as (3 * (4 - 5)) = ~3infix 4 *, infix 3 - would parse as ((3 * 4) - 5) = 7(* examples/recursive-datatypes.sml *)