6.2.2. Pattern Match
Two tasks:
Elaborate a pattern match expression
Reduce a pattern match expression: The type of a pattern match expression is a function type. When a pattern match expression is applied to its arguments we have to be able to
decide the pattern clause
bind the pattern variables of the pattern clause to subexpressions of the arguments
evaluate the body of the pattern clause with the variables bound to subexpressions
6.2.2.1. Syntax
A pattern match expression consists of an optional name (to be used for recursive calls), an optional type and a list of pattern clauses.
case
f -- optional name
{ all (x1: A1) (x2: A2) ... : R } -- optional type
\ p11 p12 ... := e1 -- one pattern for each explicit argument
\ p21 p22 ... := e2
...
\ pn1 pn2 ... := en
Pattern match expressions can be mutually recursive:
mutual
case f1 {T1}
...
...
case f2 {T2}
...
...
Syntax of pattern:
pattern ::=
| constant -- "hello", 'A', -35, 1.0
| name -- variable or constructor
| { name } -- variable
| ( compound )
compound ::=
| name := general -- deep inspection, e.g. a := x :: b
| general
general ::=
| pattern
| name pattern+ -- or in operator form e.g. 'pattern :: pattern'
6.2.2.2. Pattern Reduction
A pattern match expression can be reduced if it is in the following form:
(case {all (x: A): R} [\ p1 := e1, \ p2 := e2, ... , \ x := ex])
a1
a2
...
-- where 'a1 = c ...' if there are explicit pattern and 'c' is a constructor
Only one pattern is allowed in each clause.
If the pattern clauses are not exhaustive, then there has to be a final default clause.
No nested pattern i.e. each pattern clause except the default clause matches on one constructor where all arguments are variables.
If there constructor pattern, then the first argument
a1has to be a constructor application.
In order to reduce the expression we have to distinguish the following 2 cases:
cdoes not match any explicit pattern or there are no explicit pattern. The pattern match expression reduces toex[x := a1] a2 a3 ...
cmatches the explicit patternpi. Thena1andpihave the form:pi = (y := c {q1} {q2} ... y1 y2 ...) a1 = c {q1} {q2} ... b1 b2 ...
Note that the parameters in the pattern and the argument have to be equivalent. Otherwise the pattern match expression wouldn’t be welltyped. The pattern match expression reduces to
ei[y:=a1, y1:=b1, y2:=b2, ...] a2 a3 ...
6.2.2.3. Pattern Elaboration
Before elaborating a pattern match expression, the type of the pattern match expression has to be elaborated. Here we assume that we have an elaborated type of the pattern match expression:
all (x1: A1) (x2: A2) ... : R
Some of the arguments in the type of the pattern match expression might be implicit. All implicit arguments have to be inferable i.e. they have to occur either in one of the subsequent argument types or in the result type:
all ... {xi: Ai} ... : R -- 'xi' occurs in 'R'
all ... {xi: Ai} ... (xj: Aj) ... : R -- 'xi' occurs in 'Aj'
Implicit arguments in the type can only be matched by variable patterns. Reason: All values corresponding to implicit arguments are erased i.e. not availalble at runtime. Therefore no branching can be done depending on the value of implicit arguments.
There might be inferable variables which are not implicit. The values corresponding to explicit variables are available at runtime. Therefore constructor patterns are possible. However since they are inferable, there might be constraints to be satisfied.
In order to elaborate a pattern match expression we have to elaborate each pattern clause separately. For each pattern clause the elaboration generates:
G = [v1: V1, v2: V2, ...]: pattern variables. Each pattern variable is represented by a metavariable.[p1, p2, ...]: list of pattern expressions using pattern variablese: body of the clause using pattern variables
- Data:
all (x: A): R -- type ^ | p -- pattern to elaborate G = [v1: V1, v2: V2, ... ] -- pattern variables (metavariables) ps = [p1, p2, .... ] -- elaborated pattern expressions
We use metavariables as pattern variables because the pattern variables might be subject to constraints.
- Start:
all (x1: A1) (x2: A2) ... : R -- type of the pattern match expression ^ | p -- pattern to elaborate G = [] ps = []
- The argument in the type is implicit, but the pattern not:
I.e. the type has the form
all {x: A}: R. Since the pattern is not implicit, the pattern does not correspond to this type.Introduce a fresh metavariable
?mfor the pattern.Do the substitution
R[x := ?m].Add
{ ?m }to the patternsps.
- Pattern is an implicit argument:
I.e.
p = { name }.In that case the type has the form
all {x: A}: R.Introduce a metavariable
name.Do the substitution
R[x := name].Add
{ name }to the patternsps.
- Pattern is a constant:
I.e. it is either a string, a character or a number.
The type
Ahas to be compatible with the type of the constant. We make the substitutionR[x := constant].- Pattern is a constructor name:
This is possible only if
Ais an inductive type. Same as constructor pattern with zero arguments (see below).- Pattern is a name but not a constructor:
The name is a pattern variable and added to the pattern variables i.e. we add
name: Ato the pattern variables and make the substitutionR[x := name].- Pattern is a constructor pattern:
I.e. the pattern has the form
name p1 p2 ....In this case the type
Amust have or reduce to the formA = I q dwhereIis an inductive type,qare the actual parameter arguments anddare the actual index arguments.The name must be one of the constructor names of the inductive type.
The type of the constructor has the general form
all (b1: B1) (b2: B2) ... : I awhere all formal parameters have been replaced by the actual parametersq.Elaborate
p1,p2, … iteratively starting with the typeall (b1: B1): RwhereR = all (b2: B2) ... : I a.At the end of elaborating
p1,p2, … we get the constructed typeI awhere all argumentsb1,b2, … have been replaced by the corresponding pattern.Unify
aanddwhich might instantiate some pattern variables.The pattern is
c q p1 p2 ...wherecis an expression representing the corresponding constructor,qare the actual parameters (usually implicit) andp1,p2, … are the constructed patterns.Make the substitution
R[x := c q p1 p2 ...].
At the end of the elaboration of the patterns we have for a pattern clause:
G = [v1: V1, v2: V2, ...] -- a sequence of pattern variables
ps = [p1, p2, ... ] -- a sequence of elaborated pattern
It remains to elaborate the right hand side of the pattern clause.