3.4. TYPE DEFINITIONS 27
#fun (inr b) -> b;;
Toplevel input:
>fun (inr b) -> b;;
>^^^^^^^^^^^^^^^^
Warning: this matching is not exhaustive.
it : (’a, ’b) sum -> ’b = <fun>
If this function is applied to something of the form inl x, then it will not work:
#let f = fun (inr b) -> b;;
Toplevel input:
>let f = fun (inr b) -> b;;
> ^^^^^^^^^^^^^^^^
Warning: this matching is not exhaustive.
f : (’a, ’b) sum -> ’b = <fun>
#f (inl 3);;
Uncaught exception: Match_failure ("", 452, 468)
Though booleans are built into CAML, they are effectively defined by a rather
trivial instance of a recursive type, often called an enumerated type, where the
constructors take no arguments:
#type bool = false | true;;
Indeed, it is perfectly permissible to define things by matching over the truth
values. The following two phrases are completely equivalent:
#if 4 < 3 then 1 else 0;;
it : int = 0
#(fun true -> 1 | false -> 0) (4 < 3);;
it : int = 0
Pattern matching is, however, not limited to casewise definitions over elements
of recursive types, though it is particularly convenient there. For example, we can
define a function that tells us whether an integer is zero as follows:
#fun 0 -> true | n -> false;;
it : int -> bool = <fun>
#(fun 0 -> true | n -> false) 0;;
it : bool = true
#(fun 0 -> true | n -> false) 1;;
it : bool = false
In this case we no longer have mutual exclusivity of patterns, since 0 matches
either pattern. The patterns are examined in order, one by one, and the first
matching one is used. Note carefully that unless the matches are mutually exclusive,
there is no guarantee that each clause holds as a mathematical equation. For
example in the above, the function does not return false for any n, so the second
clause is not universally valid.
Note that only constructors may be used in the above special way as components
of patterns. Ordinary constants will be treated as new variables bound inside the
pattern. For example, consider the following: