Skip to content

Commit 430277d

Browse files
committed
Started Stlc.
1 parent 86bb04a commit 430277d

File tree

1 file changed

+64
-60
lines changed

1 file changed

+64
-60
lines changed

src/Stlc.lidr

Lines changed: 64 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -340,67 +340,71 @@ Here is the definition, informally...
340340
... and formally:
341341

342342
> mutual
343+
>
344+
> subst : String -> Tm -> Tm -> Tm
345+
> subst x s t =
346+
> case t of
347+
> Tvar x' => if x == x' then s else t
348+
> Tabs x' ty t1 =>
349+
> Tabs x' ty (if x == x' then t1 else subst x s t1)
350+
> t1 # t2 => subst x s t1 # subst x s t2
351+
> Ttrue => Ttrue
352+
> Tfalse => Tfalse
353+
> Tif t1 t2 t3 => Tif (subst x s t1) (subst x s t2) (subst x s t3)
354+
355+
> infixl 5 :=
356+
> (:=) : String -> Tm -> Tm -> Tm
357+
> (:=) x s = subst x s
358+
359+
_Technical note_: Substitution becomes trickier to define if we
360+
consider the case where `s`, the term being substituted for a
361+
variable in some other term, may itself contain free variables.
362+
Since we are only interested here in defining the `step` relation
363+
on _closed_ terms (i.e., terms like `\x:Bool. x` that include
364+
binders for all of the variables they mention), we can avoid this
365+
extra complexity here, but it must be dealt with when formalizing
366+
richer languages.
367+
368+
For example, using the definition of substitution above to
369+
substitute the _open_ term `s = \x:Bool. r`, where `r` is a _free_
370+
reference to some global resource, for the variable `z` in the
371+
term `t = \r:Bool. z`, where `r` is a bound variable, we would get
372+
`\r:Bool. \x:Bool. r`, where the free reference to `r` in `s` has
373+
been "captured" by the binder at the beginning of `t`.
374+
375+
Why would this be bad? Because it violates the principle that the
376+
names of bound variables do not matter. For example, if we rename
377+
the bound variable in `t`, e.g., let `t' = \w:Bool. z`, then
378+
``x:=s`t'` is `\w:Bool. \x:Bool. r`, which does not behave the
379+
same as ``x:=s`t = \r:Bool. \x:Bool. r`. That is, renaming a
380+
bound variable changes how `t` behaves under substitution. *)
381+
382+
See, for example, `Aydemir 2008` for further discussion
383+
of this issue.
384+
385+
==== Exercise: 3 stars (substi_correct)
386+
387+
The definition that we gave above uses Idris recursive facility
388+
to define substitution as a _function_. Suppose, instead, we
389+
wanted to define substitution as an inductive _relation_ `substi`.
390+
We've begun the definition by providing the `Inductive` header and
391+
one of the constructors; your job is to fill in the rest of the
392+
constructors and prove that the relation you've defined coincides
393+
with the function given above.
394+
395+
-- > data substi : Tm -> Tm -> Type where -- (s:Tm) (x:string) : :=
396+
-- > S_Var1 : (s:Tm) -> (x:string) -> substi s x (Tvar x) s
397+
-- > S_Var1 : (s:Tm) -> (x:string) -> substi s x (Tvar x) s
398+
--
399+
--
400+
-- > Tvar x' => if x == x' then s else t
401+
-- > Tabs x' ty t1 =>
402+
-- > Tabs x' ty (if x == x' then t1 else subst x s t1)
403+
-- > t1 # t2 => subst x s t1 # subst x s t2
404+
-- > Ttrue => Ttrue
405+
-- > Tfalse => Tfalse
406+
-- > Tif t1 t2 t3 => Tif (subst x s t1) (subst x s t2) (subst x s t3)
343407

344-
Fixpoint subst (x:string) (s:Tm) (t:Tm) : Tm :=
345-
match t with
346-
| tvar x' =>
347-
if beq_string x x' then s else t
348-
| tabs x' T t1 =>
349-
tabs x' T (if beq_string x x' then t1 else (`x:=s` t1))
350-
| tapp t1 t2 =>
351-
tapp (`x:=s` t1) (`x:=s` t2)
352-
| ttrue =>
353-
ttrue
354-
| tfalse =>
355-
tfalse
356-
| tif t1 t2 t3 =>
357-
tif (`x:=s` t1) (`x:=s` t2) (`x:=s` t3)
358-
end
359-
360-
where "'`' x ':=' s '`' t" := (subst x s t).
361-
362-
(** _Technical note_: Substitution becomes trickier to define if we
363-
consider the case where `s`, the term being substituted for a
364-
variable in some other term, may itself contain free variables.
365-
Since we are only interested here in defining the `step` relation
366-
on _closed_ terms (i.e., terms like `\x:Bool. x` that include
367-
binders for all of the variables they mention), we can avoid this
368-
extra complexity here, but it must be dealt with when formalizing
369-
richer languages. *)
370-
371-
(** For example, using the definition of substitution above to
372-
substitute the _open_ term `s = \x:Bool. r`, where `r` is a _free_
373-
reference to some global resource, for the variable `z` in the
374-
term `t = \r:Bool. z`, where `r` is a bound variable, we would get
375-
`\r:Bool. \x:Bool. r`, where the free reference to `r` in `s` has
376-
been "captured" by the binder at the beginning of `t`.
377-
378-
Why would this be bad? Because it violates the principle that the
379-
names of bound variables do not matter. For example, if we rename
380-
the bound variable in `t`, e.g., let `t' = \w:Bool. z`, then
381-
``x:=s`t'` is `\w:Bool. \x:Bool. r`, which does not behave the
382-
same as ``x:=s`t = \r:Bool. \x:Bool. r`. That is, renaming a
383-
bound variable changes how `t` behaves under substitution. *)
384-
385-
(** See, for example, `Aydemir 2008` for further discussion
386-
of this issue. *)
387-
388-
(** **** Exercise: 3 stars (substi_correct) *)
389-
(** The definition that we gave above uses Coq's `Fixpoint` facility
390-
to define substitution as a _function_. Suppose, instead, we
391-
wanted to define substitution as an inductive _relation_ `substi`.
392-
We've begun the definition by providing the `Inductive` header and
393-
one of the constructors; your job is to fill in the rest of the
394-
constructors and prove that the relation you've defined coincides
395-
with the function given above. *)
396-
397-
Inductive substi (s:Tm) (x:string) : Tm -> Tm -> Prop :=
398-
| s_var1 :
399-
substi s x (tvar x) s
400-
(* FILL IN HERE *)
401-
.
402-
403-
Hint Constructors substi.
404408

405409
Theorem substi_correct : forall s x t t',
406410
`x:=s`t = t' <-> substi s x t t'.

0 commit comments

Comments
 (0)