You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
semantics-2023/theories/type_systems/stlc/untyped.v

222 lines
5.6 KiB

From stdpp Require Import base relations tactics.
From iris Require Import prelude.
From semantics.lib Require Import sets maps.
From semantics.ts.stlc Require Import lang notation.
(** The following two lemmas will be helpful in the sequel.
They just lift multiple reduction steps (via [rtc]) to application.
*)
Lemma steps_app_r (e1 e2 e2' : expr) :
rtc step e2 e2'
rtc step (e1 e2) (e1 e2').
Proof.
induction 1 as [ e | e e' e'' Hstep Hsteps IH].
- reflexivity.
- eapply (rtc_l _ _ (e1 e')).
{ by eapply StepAppR. }
done.
Qed.
Lemma steps_app_l (e1 e1' e2 : expr) :
is_val e2
rtc step e1 e1'
rtc step (e1 e2) (e1' e2).
Proof.
intros Hv.
induction 1 as [ e | e e' e'' Hstep Hsteps IH].
- reflexivity.
- eapply (rtc_l _ _ (e' e2)).
{ by eapply StepAppL. }
done.
Qed.
(** * Untyped λ calculus *)
(** We do not re-define the language to remove primitive addition -- instead, we just
restrict our usage in this file to variables, application, and lambdas.
*)
Definition I_val : val := λ: "x", "x".
Definition F_val : val := λ: "x" "y", "x".
Definition S_val : val := λ: "x" "y", "y".
Definition ω : val := λ: "x", "x" "x".
Definition Ω : expr := ω ω.
(** Ω reduces to itself! *)
Lemma Omega_step : step Ω Ω.
Proof.
apply StepBeta. done.
Qed.
(** ** Scott encodings *)
Definition zero : val := λ: "x" "y", "x".
Definition succ (n : val) : val := λ: "x" "y", "y" n.
(** [Succ] can be seen as a constructor: it takes [n] at the level of the language. *)
Definition Succ : val := λ: "n" "x" "y", "y" "n".
Fixpoint enc_nat (n : nat) : val :=
match n with
| 0 => zero
| S n => succ (enc_nat n)
end.
Lemma enc_nat_closed n :
closed [] (enc_nat n).
Proof.
induction n as [ | n IH].
- done.
- simpl. by apply closed_weaken_nil.
Qed.
Lemma enc_0_red (z s : val) :
is_closed [] z
rtc step (enc_nat 0 z s) z.
Proof.
intros Hcl.
eapply rtc_l.
{ econstructor; first auto. econstructor. auto. }
simpl. eapply rtc_l.
{ econstructor. auto. }
simpl. rewrite subst_closed_nil; done.
Qed.
Lemma enc_S_red n (z s : val) :
rtc step (enc_nat (S n) z s) (s (enc_nat n)).
Proof.
simpl. eapply rtc_l.
{ econstructor; first auto. econstructor. auto. }
simpl. eapply rtc_l.
{ econstructor. auto. }
simpl. rewrite (subst_closed_nil (enc_nat n)); last apply enc_nat_closed.
rewrite subst_closed_nil; last apply enc_nat_closed.
reflexivity.
Qed.
Lemma Succ_red n : step (Succ (enc_nat n)) (enc_nat (S n)).
Proof. econstructor. apply is_val_val. Qed.
Lemma Succ_red_n n : rtc step (Nat.iter n Succ zero) (enc_nat n).
Proof.
induction n as [ | n IH].
- reflexivity.
- simpl.
etrans.
{ simpl. eapply steps_app_r. apply IH. }
eapply rtc_l.
{ apply Succ_red. }
reflexivity.
Qed.
(** ** Recursion *)
Definition Fix' : val := λ: "z" "y", "y" (λ: "x", "z" "z" "y" "x").
Definition Fix (s : val) : val := λ: "x", Fix' Fix' s "x".
Arguments Fix : simpl never.
Local Hint Immediate is_val_val : core.
(** We prove that it satisfies the recursive unfolding *)
Lemma Fix_step (s r : val) :
is_closed [] s
rtc step (Fix s r) (s ((Fix s))%E r).
Proof.
intros Hclosed.
eapply rtc_l.
{ econstructor. auto. }
eapply rtc_l.
{ simpl. econstructor; first by auto.
econstructor. { rewrite subst_closed_nil; auto. }
econstructor. done.
}
simpl. rewrite subst_closed_nil; last done.
eapply rtc_l.
{ econstructor; first by auto.
econstructor. auto.
}
simpl. reflexivity.
Qed.
(** Example usage: addition on Scott-encoded numbers *)
Definition add_step : val := λ: "r", λ: "n" "m", "n" "m" (λ: "p", Succ ("r" "p" "m")).
Definition add := Fix add_step.
(** We are now going to prove it correct:
[add (enc_nat n) (enc_nat m))* (enc_nat (n + m))]
First, we prove that it satisfies the expected defining equations for Peano addition.
*)
Lemma add_step_0 m : rtc step (add (enc_nat 0) (enc_nat m)) (enc_nat m).
Proof.
(* use the unfolding equation of the fixpoint combinator *)
etrans.
{ eapply steps_app_l; first by auto.
eapply Fix_step. done.
}
(* subst it into the [add_step] function *)
eapply rtc_l.
{ econstructor; auto. econstructor; auto. econstructor. auto. }
simpl.
(* subst in the zero *)
eapply rtc_l.
{ econstructor; auto. econstructor. done. }
simpl.
(* subst in the m *)
eapply rtc_l.
{ econstructor; auto. }
simpl.
(* do a step *)
etrans.
{ apply (enc_0_red (enc_nat m) (λ: "p", Succ (Fix add_step "p" (enc_nat m)))).
apply enc_nat_closed.
}
reflexivity.
Qed.
Lemma add_step_S n m : rtc step (add (enc_nat (S n)) (enc_nat m)) (Succ (add (enc_nat n) (enc_nat m))).
Proof.
(* use the unfolding equation of the fixpoint combinator *)
etrans.
{ eapply steps_app_l; first by auto.
eapply Fix_step. done.
}
(* subst it into the [add_step] function *)
eapply rtc_l.
{ econstructor; auto. econstructor; auto. econstructor. auto. }
simpl.
(* subst in the zero *)
eapply rtc_l.
{ econstructor; auto. econstructor. done. }
simpl.
(* subst in the m *)
eapply rtc_l.
{ econstructor; auto. }
simpl.
(* do a step *)
etrans.
{ rewrite subst_closed_nil; last apply enc_nat_closed.
apply (enc_S_red n (enc_nat m) (λ: "p", Succ (Fix add_step "p" (enc_nat m)))).
}
eapply rtc_l.
{ econstructor. auto. }
simpl.
rewrite subst_closed_nil; last apply enc_nat_closed.
reflexivity.
Qed.
Lemma add_correct n m : rtc step (add (enc_nat n) (enc_nat m)) (enc_nat (n + m)).
Proof.
induction n as [ | n IH].
- apply add_step_0.
- etrans. { apply add_step_S. }
etrans. { apply steps_app_r. apply IH. }
eapply rtc_l. { apply Succ_red. }
reflexivity.
Qed.