Section 8.9 .2 on page 499 describes checks for exhaustive and redundant patterns. Given a scrutinee of type $\tau$, a set of patterns is exhaustive if every value that inhabits type $\tau$ is matched by some pattern. In this exercise you write an analysis that prints a warning message when it finds a non-exhaustive or redundant pattern match.
The idea is this: Suppose you have the set of all possible values of type $\tau$. And suppose that, for each member of this set, you can tell if it does or does not match a particular pattern $p$. Then you can check for both exhaustiveness and redundancy using an iterative algorithm that maintains a set of all values not yet matched.
($\bullet$ The set is initially the set of all values of type $\tau$.
($\bullet$ At each step of the iteration, the set is split into two subsets: those that do and do not match pattern $p$.
($\bullet$ The set that matches $p$ must not be empty; otherwise pattern $p$ is redundant.
($\bullet$ The set that does not match $p$ is passed on to the next pattern.
($\bullet$ At the end of the iteration, if the set of values not yet matched is nonempty, the pattern match is not exhaustive.
There's only one snag: for interesting types, the sets are infinite. To represent such sets, I define a "simple value set" to be one of two choices:
($\bullet$ All values of type $\tau$, for a given $\tau$
- A given value constructor $K$, applied to a list of zero or more simple value sets
A full set of values is a collection of simple sets, using the collections defined in Section H.2.4 (page S218).
520. $\langle$ exhaustiveness analysis for $\mu M L 520\rangle \equiv$
(S420b) $521 \mathrm{~b} D$
datatype simple_vset $=$ ALL of ty
I ONE of vcon* simple_vset list
type vset $=$ simple_vset collection
In the analysis, each set of values is classified according to whether it does or does not match a pattern. Full sets can be classified, simple sets can be classified, and even lists of sets can be classified. Start with this code:
Classification takes a single value set as input and produces a collection as output. A simple value set $v$ is classified by a pattern $p$ as follows:
($\bullet$ If $p$ is a wildcard or a variable, it always matches, and the result is a singleton collection containing (true, vs).
($\bullet$ If $p$ is ( $K p_1 \cdots p_n$ ) and $v s$ is the application of a different constructor $K^{\prime}$, then $v$ doesn't match, and the result is a singleton collection containing (false, vs).
($\bullet$ If $p$ is ( $\left.K p_1 \cdots p_n\right)$ and $v$ is (K $v_1 \cdots v_n$ ), then the value-set list $v_1 \cdots v_n$ is classified against the pattern list $p_1 \cdots p_n$. Do this using a third function, classifyList. The empty value-set list always matches the empty pattern list, and the subset of $v_1 \cdots v_n$ matching $p_1 \cdots p_n$ is the subset of $v_1$ matching $p_1$ combined with the subset of $v_2 \cdots v_n$ matching $p_2 \cdots p_n$. To implement classifyList, use recursion, use classifySimple, and use the collection function map2C.
($\bullet$ Finally, if $p$ is ( $K p_1 \cdots p_n$ ) and $v$ is ALL $\tau$, change ALL $\tau$ to unroll $\tau$ and try again. When $\tau$ is an algebraic data type, unroll $\tau$ returns a vset that is equivalent to $\mathrm{ALL} \tau$ but that does not use ALL at top level.
Function call vcons 0 mu returns the name and type scheme of each value constructor associated with mu. Function vcons 0 is omitted from this book.
Using this classification, the exhaustiveness check can be implemented in three stages, as described on the next page.
Implement the exhaustiveness check in three stages:
(a) Implement classifySimple, but leave out the case of matching value constructors.
(b) Implement classifyList, which has type pat list * simple_vset list $\rightarrow$ (bool * simple_vset list) collection, and use it to complete the implementation of classifySimple. Classify lists using these rules:
($\bullet$ The empty list of values always matches the empty list of patterns.
($\bullet$ A list of values $v:: v s$ matches a list of patterns $p:: p s$ if and only if $v$ matches $p$ and also $v s$ matches $p s$.
(c) Implement exhaustivenessCheck, replacing this placeholder:
The replacement should compute successive value sets that are as yet unmatched. Start with the value-set collection singleC (ALL tau), and classify value sets using each pattern from ps in turn. Issue a warning message for each redundant pattern, and if the list of patterns is not exhaustive, issue a warning for that too.