1.10 Pattern matching and recursion
The natural numbers introduce an additional subtlety over the types considered up until now.
In the case of coproducts, for instance, we could define a function f:A+BβC either with the recursor:
f:β‘ππΎπΌA+B(C,g0,g1) |
or by giving the defining equations:
f(πππ (a)) | :β‘g0(a) | ||
f(πππ(b)) | :β‘g1(b). |
To go from the former expression of f to the latter, we simply use the computation rules for the recursor. Conversely, given any defining equations
f(πππ (a)) | :β‘Ξ¦0 | ||
f(πππ(b)) | :β‘Ξ¦1 |
where Ξ¦0 and Ξ¦1 are expressions that may involve the variables a and b respectively, we can express these equations equivalently in terms of the recursor by using Ξ»-abstraction:
f:β‘ππΎπΌA+B(C,Ξ»a.Ξ¦0,Ξ»b.Ξ¦1). |
In the case of the natural numbers, however, the βdefining equationsβ of a function such as π½πππ»π πΎ:
π½πππ»π πΎ(0) | :β‘0 | (1) | ||
π½πππ»π πΎ(πππΌπΌ(n)) | :β‘πππΌπΌ(πππΌπΌ(π½πππ»π πΎ(n))) | (2) |
involve the function double itself on the right-hand side. However, we would still like to be able to give these equations, rather than (LABEL:eq:dbl-as-rec), as the definition of π½πππ»π πΎ, since they are much more convenient and readable. The solution is to read the expression βπ½πππ»π πΎ(n)β on the right-hand side of (2) as standing in for the result of the recursive call, which in a definition of the form π½πππ»π πΎ:β‘ππΎπΌβ(β,c0,cs) would be the second argument of cs.
More generally, if we have a βdefinitionβ of a function f:ββC such as
f(0) | :β‘Ξ¦0 | ||
f(πππΌπΌ(n)) | :β‘Ξ¦s |
where Ξ¦0 is an expression of type C, and Ξ¦s is an expression of type C which may involve the variable n and also the symbol βf(n)β, we may translate it to a definition
f:β‘ππΎπΌβ(C,Ξ¦0,Ξ»n.Ξ»r.Ξ¦β²s) |
where Ξ¦β²s is obtained from Ξ¦s by replacing all occurrences of βf(n)β by the new variable r.
This style of defining functions by recursion (or, more generally, dependent functions by induction) is so convenient that we frequently adopt it.
It is called definition by pattern matching.
Of course, it is very similar to how a computer programmer may define a recursive function
with a body that literally contains recursive calls to itself.
However, unlike the programmer, we are restricted in what sort of recursive calls we can make: in order for such a definition to be re-expressible using the recursion principle, the function f being defined can only appear in the body of f(πππΌπΌ(n)) as part of the composite symbol βf(n)β.
Otherwise, we could write nonsense functions such as
f(0) | :β‘0 | ||
f(πππΌπΌ(n)) | :β‘f(πππΌπΌ(πππΌπΌ(n))). |
If a programmer wrote such a function, it would simply call itself forever on any positive input, going into an infinite loop and never returning a value. In mathematics, however, to be worthy of the name, a function must always associate a unique output value to every input value, so this would be unacceptable.
This point will be even more important when we introduce more complicated inductive types in http://planetmath.org/node/87578Chapter 5,http://planetmath.org/node/87579Chapter 6,http://planetmath.org/node/87585Chapter 11. Whenever we introduce a new kind of inductive definition, we always begin by deriving its induction principle. Only then do we introduce an appropriate sort of βpattern matchingβ which can be justified as a shorthand for the induction principle.
Title | 1.10 Pattern matching and recursion |
---|---|
\metatable |