first draft of Stlc complete to beginning of types
This commit is contained in:
parent
daf8cda196
commit
1738eb3998
1 changed files with 297 additions and 35 deletions
332
src/Stlc.lagda
332
src/Stlc.lagda
|
@ -113,22 +113,20 @@ data Term : Set where
|
||||||
if_then_else_ : Term → Term → Term → Term
|
if_then_else_ : Term → Term → Term → Term
|
||||||
\end{code}
|
\end{code}
|
||||||
|
|
||||||
#### Unicode
|
#### Special characters
|
||||||
|
|
||||||
We use the following unicode characters
|
We use the following special characters
|
||||||
|
|
||||||
` U+0060: GRAVE ACCENT
|
⇒ U+21D2: RIGHTWARDS DOUBLE ARROW (\=>)
|
||||||
λ U+03BB GREEK SMALL LETTER LAMBDA
|
` U+0060: GRAVE ACCENT
|
||||||
∶ U+2236 RATIO
|
λ U+03BB: GREEK SMALL LETTER LAMBDA (\Gl or \lambda)
|
||||||
· U+00B7: MIDDLE DOT
|
∶ U+2236: RATIO (\:)
|
||||||
|
· U+00B7: MIDDLE DOT (\cdot)
|
||||||
|
|
||||||
In particular, ∶ (U+2236 RATIO) is not the same as : (U+003A COLON).
|
Note that ∶ (U+2236 RATIO) is not the same as : (U+003A COLON).
|
||||||
Colon is reserved in Agda for declaring types. Everywhere that we
|
Colon is reserved in Agda for declaring types. Everywhere that we
|
||||||
declare a type in the object language rather than Agda we will use
|
declare a type in the object language rather than Agda we use
|
||||||
ratio in place of colon, otherwise our code will not parse. Recall
|
ratio in place of colon.
|
||||||
that in Agda one may treat square brackets `[]` as ordinary symbols,
|
|
||||||
while round parentheses `()` and curly braces `{}` have special
|
|
||||||
meaning.
|
|
||||||
|
|
||||||
Using ratio for this purpose is arguably a bad idea, because one must use context
|
Using ratio for this purpose is arguably a bad idea, because one must use context
|
||||||
rather than appearance to distinguish it from colon. Arguably, it might be
|
rather than appearance to distinguish it from colon. Arguably, it might be
|
||||||
|
@ -136,7 +134,9 @@ better to use a different symbol, such as `∈` or `::`. We reserve `∈`
|
||||||
for use later to indicate that a variable appears free in a term, and
|
for use later to indicate that a variable appears free in a term, and
|
||||||
eschew `::` because we consider it too ugly.
|
eschew `::` because we consider it too ugly.
|
||||||
|
|
||||||
#### Formal vs Informal
|
|
||||||
|
|
||||||
|
#### Formal vs informal
|
||||||
|
|
||||||
In informal presentation of formal semantics, one uses choice of
|
In informal presentation of formal semantics, one uses choice of
|
||||||
variable name to disambiguate and writes `x` rather than `` ` x ``
|
variable name to disambiguate and writes `x` rather than `` ` x ``
|
||||||
|
@ -144,11 +144,13 @@ for a term that is a variable. Agda requires we distinguish.
|
||||||
Often researchers use `var x` rather than `` ` x ``, but we chose
|
Often researchers use `var x` rather than `` ` x ``, but we chose
|
||||||
the latter since it is closer to the informal notation `x`.
|
the latter since it is closer to the informal notation `x`.
|
||||||
|
|
||||||
Similarly, informal presentation often use the notations
|
Similarly, informal presentation often use the notations `A → B` for
|
||||||
`A → B` for functions, `λ x . N` for abstractions, and `L M` for applications.
|
functions, `λ x . N` for abstractions, and `L M` for applications. We
|
||||||
We cannot use these, because they overlap with the notation used by Agda.
|
cannot use these, because they overlap with the notation used by Agda.
|
||||||
Some researchers use `L @ M` in place of `L · M`, but we cannot
|
In `λ[ x ∶ A ] N`, recall that Agda treats square brackets `[]` as
|
||||||
because `@` has a reserved meaning in Agda.
|
ordinary symbols, while round parentheses `()` and curly braces `{}`
|
||||||
|
have special meaning. We would use `L @ M` for application, but
|
||||||
|
`@` has a reserved meaning in Agda.
|
||||||
|
|
||||||
|
|
||||||
#### Examples
|
#### Examples
|
||||||
|
@ -159,9 +161,10 @@ Here are a couple of example terms, `not` of type
|
||||||
and applies the function to the boolean twice.
|
and applies the function to the boolean twice.
|
||||||
|
|
||||||
\begin{code}
|
\begin{code}
|
||||||
f x : Id
|
f x y : Id
|
||||||
f = id 0
|
f = id 0
|
||||||
x = id 1
|
x = id 1
|
||||||
|
y = id 2
|
||||||
|
|
||||||
not two : Term
|
not two : Term
|
||||||
not = λ[ x ∶ 𝔹 ] (if ` x then false else true)
|
not = λ[ x ∶ 𝔹 ] (if ` x then false else true)
|
||||||
|
@ -189,15 +192,15 @@ to be weaker than application. For instance,
|
||||||
> `` (λ[ f ∶ 𝔹 ⇒ 𝔹 ] (λ[ x ∶ 𝔹 ] ` f)) · (` f · ` x) ``.
|
> `` (λ[ f ∶ 𝔹 ⇒ 𝔹 ] (λ[ x ∶ 𝔹 ] ` f)) · (` f · ` x) ``.
|
||||||
|
|
||||||
\begin{code}
|
\begin{code}
|
||||||
example₁ : (𝔹 ⇒ 𝔹) ⇒ 𝔹 ⇒ 𝔹 ≡ (𝔹 ⇒ 𝔹) ⇒ (𝔹 ⇒ 𝔹)
|
ex₁ : (𝔹 ⇒ 𝔹) ⇒ 𝔹 ⇒ 𝔹 ≡ (𝔹 ⇒ 𝔹) ⇒ (𝔹 ⇒ 𝔹)
|
||||||
example₁ = refl
|
ex₁ = refl
|
||||||
|
|
||||||
example₂ : two · not · true ≡ (two · not) · true
|
ex₂ : two · not · true ≡ (two · not) · true
|
||||||
example₂ = refl
|
ex₂ = refl
|
||||||
|
|
||||||
example₃ : λ[ f ∶ 𝔹 ⇒ 𝔹 ] λ[ x ∶ 𝔹 ] ` f · (` f · ` x)
|
ex₃ : λ[ f ∶ 𝔹 ⇒ 𝔹 ] λ[ x ∶ 𝔹 ] ` f · (` f · ` x)
|
||||||
≡ (λ[ f ∶ 𝔹 ⇒ 𝔹 ] (λ[ x ∶ 𝔹 ] (` f · (` f · ` x))))
|
≡ (λ[ f ∶ 𝔹 ⇒ 𝔹 ] (λ[ x ∶ 𝔹 ] (` f · (` f · ` x))))
|
||||||
example₃ = refl
|
ex₃ = refl
|
||||||
\end{code}
|
\end{code}
|
||||||
|
|
||||||
#### Quiz
|
#### Quiz
|
||||||
|
@ -228,16 +231,22 @@ example₃ = refl
|
||||||
|
|
||||||
## Values
|
## Values
|
||||||
|
|
||||||
|
We only consider reduction of _closed_ terms,
|
||||||
|
those that contain no free variables. We consider
|
||||||
|
a precise definition of free variables in
|
||||||
|
[StlcProp]({{ "StlcProp" | relative_url }}).
|
||||||
|
|
||||||
A term is a value if it is fully reduced.
|
A term is a value if it is fully reduced.
|
||||||
|
For booleans, the situation is clear, `true` and
|
||||||
For booleans, the situtation is clear, `true` and
|
|
||||||
`false` are values, while conditionals are not.
|
`false` are values, while conditionals are not.
|
||||||
|
|
||||||
For functions, applications are not values, because
|
For functions, applications are not values, because
|
||||||
we expect them to further reduce, and variables are
|
we expect them to further reduce, and variables are
|
||||||
not values, because we focus on closed terms
|
not values, because we focus on closed terms
|
||||||
(which never contain unbound variables).
|
(which never contain unbound variables).
|
||||||
|
Following convention, we treat all abstractions
|
||||||
|
as values.
|
||||||
|
|
||||||
|
The predicate `Value M` holds if term `M` is a value.
|
||||||
|
|
||||||
\begin{code}
|
\begin{code}
|
||||||
data Value : Term → Set where
|
data Value : Term → Set where
|
||||||
|
@ -246,8 +255,71 @@ data Value : Term → Set where
|
||||||
value-false : Value false
|
value-false : Value false
|
||||||
\end{code}
|
\end{code}
|
||||||
|
|
||||||
|
We let `V` and `W` range over values.
|
||||||
|
|
||||||
|
|
||||||
|
#### Formal vs informal
|
||||||
|
|
||||||
|
In informal presentations of formal semantics, using
|
||||||
|
`V` as the name of a metavariable is sufficient to
|
||||||
|
indicate that it is a value. In Agda, we must explicitly
|
||||||
|
invoke the `Value` predicate.
|
||||||
|
|
||||||
|
#### Other approaches
|
||||||
|
|
||||||
|
An alternative is not to focus on closed terms,
|
||||||
|
to treat variables as values, and to treat
|
||||||
|
`λ[ x ∶ A ] N` as a value only if `N` is a value.
|
||||||
|
Indeed, this is how Agda normalises terms.
|
||||||
|
Formalising this approach requires a more sophisticated
|
||||||
|
definition of substitution, which permits substituting
|
||||||
|
closed terms for values.
|
||||||
|
|
||||||
## Substitution
|
## Substitution
|
||||||
|
|
||||||
|
The heart of lambda calculus is the operation of
|
||||||
|
substituting one term for a variable in another term.
|
||||||
|
Substitution plays a key role in defining the
|
||||||
|
operational semantics of function application.
|
||||||
|
For instance, we have
|
||||||
|
|
||||||
|
(λ[ f ∶ 𝔹 ⇒ 𝔹 ] `f · (`f · true)) · not
|
||||||
|
⟹
|
||||||
|
not · (not · true)
|
||||||
|
|
||||||
|
where we substitute `false` for `` `x `` in the body
|
||||||
|
of the function abstraction.
|
||||||
|
|
||||||
|
We write substitution as `N [ x := V ]`, meaning
|
||||||
|
substitute term `V` for free occurrences of variable `x` in term `V`,
|
||||||
|
or, more compactly, substitute `V` for `x` in `N`.
|
||||||
|
Substitution works if `V` is any closed term;
|
||||||
|
it need not be a value, but we use `V` since we
|
||||||
|
always substitute values.
|
||||||
|
|
||||||
|
Here are some examples.
|
||||||
|
|
||||||
|
* `` ` f [ f := not ] `` yields `` not ``
|
||||||
|
* `` true [ f := not ] `` yields `` true ``
|
||||||
|
* `` (` f · true) [ f := not ] `` yields `` not · true ``
|
||||||
|
* `` (` f · (` f · true)) [ f := not ] `` yields `` not · (not · true) ``
|
||||||
|
* `` (λ[ x ∶ 𝔹 ] ` f · (` f · ` x)) [ f := not ] `` yields `` λ[ x ∶ 𝔹 ] not · (not · ` x) ``
|
||||||
|
* `` (λ[ y ∶ 𝔹 ] ` y) [ x := true ] `` yields `` λ[ y ∶ 𝔹 ] ` y ``
|
||||||
|
* `` (λ[ x ∶ 𝔹 ] ` x) [ x := true ] `` yields `` λ[ x ∶ 𝔹 ] ` x ``
|
||||||
|
|
||||||
|
The last example is important: substituting `true` for `x` in
|
||||||
|
`` (λ[ x ∶ 𝔹 ] ` x) `` does _not_ yield `` (λ[ x ∶ 𝔹 ] true) ``.
|
||||||
|
The reason for this is that `x` in the body of `` (λ[ x ∶ 𝔹 ] ` x) ``
|
||||||
|
is _bound_ by the abstraction. An important feature of abstraction
|
||||||
|
is that the choice of bound names is irrelevant: both
|
||||||
|
`` (λ[ x ∶ 𝔹 ] ` x) `` and `` (λ[ y ∶ 𝔹 ] ` y) `` stand for the
|
||||||
|
identity function. The way to think of this is that `x` within
|
||||||
|
the body of the abstraction stands for a _different_ variable than
|
||||||
|
`x` outside the abstraction, they both just happen to have the same
|
||||||
|
name.
|
||||||
|
|
||||||
|
Here is the formal definition in Agda.
|
||||||
|
|
||||||
\begin{code}
|
\begin{code}
|
||||||
_[_:=_] : Term → Id → Term → Term
|
_[_:=_] : Term → Id → Term → Term
|
||||||
(` x′) [ x := V ] with x ≟ x′
|
(` x′) [ x := V ] with x ≟ x′
|
||||||
|
@ -263,14 +335,121 @@ _[_:=_] : Term → Id → Term → Term
|
||||||
if (L′ [ x := V ]) then (M′ [ x := V ]) else (N′ [ x := V ])
|
if (L′ [ x := V ]) then (M′ [ x := V ]) else (N′ [ x := V ])
|
||||||
\end{code}
|
\end{code}
|
||||||
|
|
||||||
## Reduction rules
|
The two key cases are variables and abstraction.
|
||||||
|
|
||||||
|
* For variables, we compare `x`, the variable we are substituting for,
|
||||||
|
with `x′`, the variable in the term. If they are the same,
|
||||||
|
we yield `V`, otherwise we yield `x′` unchanged.
|
||||||
|
|
||||||
|
* For abstractions, we compare `x`, the variable we are substituting for,
|
||||||
|
with `x′`, the variable bound in the abstraction. If they are the same,
|
||||||
|
we yield abstraction unchanged, otherwise we subsititute inside the body.
|
||||||
|
|
||||||
|
In all other cases, we push substitution recursively into
|
||||||
|
the subterms.
|
||||||
|
|
||||||
|
#### Special characters
|
||||||
|
|
||||||
|
′ U+2032: PRIME (\')
|
||||||
|
|
||||||
|
Note that ′ (U+2032: PRIME) is not the same as ' (U+0027: APOSTROPHE).
|
||||||
|
|
||||||
|
|
||||||
|
#### Examples
|
||||||
|
|
||||||
|
Here is confirmation that the examples above are correct.
|
||||||
|
|
||||||
|
\begin{code}
|
||||||
|
ex₁₁ : ` f [ f := not ] ≡ not
|
||||||
|
ex₁₁ = refl
|
||||||
|
|
||||||
|
ex₁₂ : true [ f := not ] ≡ true
|
||||||
|
ex₁₂ = refl
|
||||||
|
|
||||||
|
ex₁₃ : (` f · true) [ f := not ] ≡ not · true
|
||||||
|
ex₁₃ = refl
|
||||||
|
|
||||||
|
ex₁₄ : (` f · (` f · true)) [ f := not ] ≡ not · (not · true)
|
||||||
|
ex₁₄ = refl
|
||||||
|
|
||||||
|
ex₁₅ : (λ[ x ∶ 𝔹 ] ` f · (` f · ` x)) [ f := not ] ≡ λ[ x ∶ 𝔹 ] not · (not · ` x)
|
||||||
|
ex₁₅ = refl
|
||||||
|
|
||||||
|
ex₁₆ : (λ[ y ∶ 𝔹 ] ` y) [ x := true ] ≡ λ[ y ∶ 𝔹 ] ` y
|
||||||
|
ex₁₆ = refl
|
||||||
|
|
||||||
|
ex₁₇ : (λ[ x ∶ 𝔹 ] ` x) [ x := true ] ≡ λ[ x ∶ 𝔹 ] ` x
|
||||||
|
ex₁₇ = refl
|
||||||
|
\end{code}
|
||||||
|
|
||||||
|
#### Quiz
|
||||||
|
|
||||||
|
What is the result of the following substitution?
|
||||||
|
|
||||||
|
(λ[ y ∶ 𝔹 ] ` x · (λ[ x ∶ 𝔹 ] ` x)) [ x := true ]
|
||||||
|
|
||||||
|
1. `` (λ[ y ∶ 𝔹 ] ` x · (λ[ x ∶ 𝔹 ] ` x)) ``
|
||||||
|
2. `` (λ[ y ∶ 𝔹 ] ` x · (λ[ x ∶ 𝔹 ] true)) ``
|
||||||
|
3. `` (λ[ y ∶ 𝔹 ] true · (λ[ x ∶ 𝔹 ] ` x)) ``
|
||||||
|
4. `` (λ[ y ∶ 𝔹 ] true · (λ[ x ∶ 𝔹 ] ` true)) ``
|
||||||
|
|
||||||
|
|
||||||
|
## Reduction
|
||||||
|
|
||||||
|
We give the reduction rules for call-by-value lambda calculus. To
|
||||||
|
reduce an application, first we reduce the left-hand side until it
|
||||||
|
becomes a value (which must be an abstraction); then we reduce the
|
||||||
|
right-hand side until it becomes a value; and finally we substitute
|
||||||
|
the argument for the variable in the abstraction. To reduce a
|
||||||
|
conditional, we first reduce the condition until it becomes a value;
|
||||||
|
if the condition is true the conditional reduces to the first
|
||||||
|
branch and if false it reduces to the second branch.a
|
||||||
|
|
||||||
|
In an informal presentation of the formal semantics, the rules
|
||||||
|
are written as follows.
|
||||||
|
|
||||||
|
L ⟹ L′
|
||||||
|
--------------- ξ·₁
|
||||||
|
L · M ⟹ L′ · M
|
||||||
|
|
||||||
|
Value V
|
||||||
|
M ⟹ M′
|
||||||
|
--------------- ξ·₂
|
||||||
|
V · M ⟹ V · M′
|
||||||
|
|
||||||
|
Value V
|
||||||
|
--------------------------------- βλ·
|
||||||
|
(λ[ x ∶ A ] N) · V ⟹ N [ x := V ]
|
||||||
|
|
||||||
|
L ⟹ L′
|
||||||
|
----------------------------------------- ξif
|
||||||
|
if L then M else N ⟹ if L′ then M else N
|
||||||
|
|
||||||
|
-------------------------- βif-true
|
||||||
|
if true then M else N ⟹ M
|
||||||
|
|
||||||
|
--------------------------- βif-false
|
||||||
|
if false then M else N ⟹ N
|
||||||
|
|
||||||
|
As we will show later, the rules are deterministic, in that
|
||||||
|
at most one rule applies to every term. As we will also show
|
||||||
|
later, for every well-typed term either a reduction applies
|
||||||
|
or it is a value.
|
||||||
|
|
||||||
|
The rules break into two sorts. Compatibility rules
|
||||||
|
direct us to reduce some part of a term.
|
||||||
|
We give them names starting with the Greek letter xi, `ξ`.
|
||||||
|
Once a term is sufficiently
|
||||||
|
reduced, it will consist of a constructor and
|
||||||
|
a deconstructor, in our case `λ` and `·`, or
|
||||||
|
`if` and `true`, or `if` and `false`.
|
||||||
|
We give them names starting with the Greek letter beta, `β`,
|
||||||
|
and indeed such rules are traditionally called beta rules.
|
||||||
|
|
||||||
\begin{code}
|
\begin{code}
|
||||||
infix 10 _⟹_
|
infix 10 _⟹_
|
||||||
|
|
||||||
data _⟹_ : Term → Term → Set where
|
data _⟹_ : Term → Term → Set where
|
||||||
βλ· : ∀ {x A N V} → Value V →
|
|
||||||
(λ[ x ∶ A ] N) · V ⟹ N [ x := V ]
|
|
||||||
ξ·₁ : ∀ {L L′ M} →
|
ξ·₁ : ∀ {L L′ M} →
|
||||||
L ⟹ L′ →
|
L ⟹ L′ →
|
||||||
L · M ⟹ L′ · M
|
L · M ⟹ L′ · M
|
||||||
|
@ -278,17 +457,78 @@ data _⟹_ : Term → Term → Set where
|
||||||
Value V →
|
Value V →
|
||||||
M ⟹ M′ →
|
M ⟹ M′ →
|
||||||
V · M ⟹ V · M′
|
V · M ⟹ V · M′
|
||||||
|
βλ· : ∀ {x A N V} → Value V →
|
||||||
|
(λ[ x ∶ A ] N) · V ⟹ N [ x := V ]
|
||||||
|
ξif : ∀ {L L′ M N} →
|
||||||
|
L ⟹ L′ →
|
||||||
|
if L then M else N ⟹ if L′ then M else N
|
||||||
βif-true : ∀ {M N} →
|
βif-true : ∀ {M N} →
|
||||||
if true then M else N ⟹ M
|
if true then M else N ⟹ M
|
||||||
βif-false : ∀ {M N} →
|
βif-false : ∀ {M N} →
|
||||||
if false then M else N ⟹ N
|
if false then M else N ⟹ N
|
||||||
ξif : ∀ {L L′ M N} →
|
|
||||||
L ⟹ L′ →
|
|
||||||
if L then M else N ⟹ if L′ then M else N
|
|
||||||
\end{code}
|
\end{code}
|
||||||
|
|
||||||
|
#### Special characters
|
||||||
|
|
||||||
|
We use the following special characters
|
||||||
|
|
||||||
|
⟹ U+27F9: LONG RIGHTWARDS DOUBLE ARROW (\r6)
|
||||||
|
ξ U+03BE: GREEK SMALL LETTER XI (\Gx or \xi)
|
||||||
|
β U+03B2: GREEK SMALL LETTER BETA (\Gb or \beta)
|
||||||
|
|
||||||
|
#### Quiz
|
||||||
|
|
||||||
|
What does the following term step to?
|
||||||
|
|
||||||
|
(λ[ x ∶ 𝔹 ⇒ 𝔹 ] ` x) · (λ [ x ∶ 𝔹 ] ` x) ⟹ ???
|
||||||
|
|
||||||
|
1. `` (λ [ x ∶ 𝔹 ] ` x) ``
|
||||||
|
2. `` (λ[ x ∶ 𝔹 ⇒ 𝔹 ] ` x) ``
|
||||||
|
3. `` (λ[ x ∶ 𝔹 ⇒ 𝔹 ] ` x) · (λ [ x ∶ 𝔹 ] ` x) ``
|
||||||
|
|
||||||
|
What does the following term step to?
|
||||||
|
|
||||||
|
(λ[ x ∶ 𝔹 ⇒ 𝔹 ] ` x) · ((λ[ x ∶ 𝔹 ⇒ 𝔹 ] ` x) (λ [ x ∶ 𝔹 ] ` x)) ⟹ ???
|
||||||
|
|
||||||
|
1. `` (λ [ x ∶ 𝔹 ] ` x) ``
|
||||||
|
2. `` (λ[ x ∶ 𝔹 ⇒ 𝔹 ] ` x) ``
|
||||||
|
3. `` (λ[ x ∶ 𝔹 ⇒ 𝔹 ] ` x) · (λ [ x ∶ 𝔹 ] ` x) ``
|
||||||
|
|
||||||
|
What does the following term step to? (Where `not` is as defined above.)
|
||||||
|
|
||||||
|
not · true ⟹ ???
|
||||||
|
|
||||||
|
1. `` if ` x then false else true ``
|
||||||
|
2. `` if true then false else true ``
|
||||||
|
3. `` true ``
|
||||||
|
4. `` false ``
|
||||||
|
|
||||||
|
What does the following term step to? (Where `two` and `not` are as defined above.)
|
||||||
|
|
||||||
|
two · not · true ⟹ ???
|
||||||
|
|
||||||
|
1. `` not · (not · true) ``
|
||||||
|
2. `` (λ[ x ∶ 𝔹 ] not · (not · ` x)) · true ``
|
||||||
|
4. `` true ``
|
||||||
|
5. `` false ``
|
||||||
|
|
||||||
## Reflexive and transitive closure
|
## Reflexive and transitive closure
|
||||||
|
|
||||||
|
A single step is only part of the story. In general, we wish to repeatedly
|
||||||
|
step a closed term until it reduces to a value. We do this by defining
|
||||||
|
the reflexive and transitive closure `⟹*` of the step function `⟹`.
|
||||||
|
In an informal presentation of the formal semantics, the rules
|
||||||
|
are written as follows.
|
||||||
|
|
||||||
|
------- done
|
||||||
|
M ⟹* M
|
||||||
|
|
||||||
|
L ⟹ M
|
||||||
|
M ⟹* N
|
||||||
|
------- step
|
||||||
|
L ⟹* N
|
||||||
|
|
||||||
|
Here it is formalised in Agda.
|
||||||
|
|
||||||
\begin{code}
|
\begin{code}
|
||||||
infix 10 _⟹*_
|
infix 10 _⟹*_
|
||||||
|
@ -298,7 +538,21 @@ infix 3 _∎
|
||||||
data _⟹*_ : Term → Term → Set where
|
data _⟹*_ : Term → Term → Set where
|
||||||
_∎ : ∀ M → M ⟹* M
|
_∎ : ∀ M → M ⟹* M
|
||||||
_⟹⟨_⟩_ : ∀ L {M N} → L ⟹ M → M ⟹* N → L ⟹* N
|
_⟹⟨_⟩_ : ∀ L {M N} → L ⟹ M → M ⟹* N → L ⟹* N
|
||||||
|
\end{code}
|
||||||
|
|
||||||
|
We can read this as follows.
|
||||||
|
|
||||||
|
* From term `M`, we can take no steps, giving `M ∎` of type `M ⟹* M`.
|
||||||
|
|
||||||
|
* From term `L` we can take a single step `L⟹M` of type `L ⟹ M`
|
||||||
|
followed by zero or more steps `M⟹*N` of type `M ⟹* N`,
|
||||||
|
giving `L ⟨ L⟹M ⟩ M⟹*N` of type `L ⟹* N`.
|
||||||
|
|
||||||
|
The names of the two clauses in the definition of reflexive
|
||||||
|
and transitive closure have been chosen to allow us to lay
|
||||||
|
out example reductions in an appealing way.
|
||||||
|
|
||||||
|
\begin{code}
|
||||||
reduction₁ : not · true ⟹* false
|
reduction₁ : not · true ⟹* false
|
||||||
reduction₁ =
|
reduction₁ =
|
||||||
not · true
|
not · true
|
||||||
|
@ -326,9 +580,17 @@ reduction₂ =
|
||||||
∎
|
∎
|
||||||
\end{code}
|
\end{code}
|
||||||
|
|
||||||
|
<!--
|
||||||
Much of the above, though not all, can be filled in using C-c C-r and C-c C-s.
|
Much of the above, though not all, can be filled in using C-c C-r and C-c C-s.
|
||||||
|
-->
|
||||||
|
|
||||||
|
#### Special characters
|
||||||
|
|
||||||
|
We use the following special characters
|
||||||
|
|
||||||
|
∎ U+220E: END OF PROOF (\qed)
|
||||||
|
⟨ U+27E8: MATHEMATICAL LEFT ANGLE BRACKET (\<)
|
||||||
|
⟩ U+27E9: MATHEMATICAL RIGHT ANGLE BRACKET (\>)
|
||||||
|
|
||||||
## Type rules
|
## Type rules
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue