Enumerative Datatypes

The simplest form of datatypes is for enumerating a finite number of constants. For instance, the following concrete syntax introduces a datatype of the name wday:

datatype wday = | Monday of () | Tuesday of () | Wednesday of () | Thursday of () | Friday of () | Saturday of () | Sunday of () // end of [wday]

where the first bar symbol (|) is optional. There are 7 nullary constructors introduced in the datatype declaration: Monday through Sunday, which are for constructing values of the type wday. For instance, Monday() is a value of the type wday. Given a nullary constructor C, we can write C for C() as a value. For instance, we can write Monday for Monday(). However, one should not assume that Tuesday is something like Monday+1.

The following code implements a function that tests whether a given value of the type wday is a weekday or not:

fun isWeekday (x: wday): bool = case x of | Monday() => true // the first bar (|) is optional | Tuesday() => true | Wednesday() => true | Thursday() => true | Friday() => true | Saturday() => false | Sunday() => false // end of [isWeekday]

Given a unary constructor C, C() is a pattern that can only match the value C(). Note that C() cannot be written as C when it is used as a pattern. If Monday() is written as Monday in the body of the function isWeekday, then an error message is to be reported during typechecking, indicating that all the clauses after the first one are redundant. This is simply due to Monday being treated as a variable pattern, which is matched by any value. A likely more sensible implementation of isWeekday is given as follows:

fun isWeekday (x: wday): bool = case x of | Saturday() => false | Sunday() => false | _ => true // end of [isWeekday]

This implementation works because pattern-matching is done sequentially at run-time: If a value of the type wday does not match either of Saturday() and Sunday(), then it must match one of Monday() , Tuesday() , Wednesday() , Thursday(), and Friday().