Lecture notes 20210519 Lambda Calculus 1
Require Import Coq.ZArith.ZArith.
Require Import Coq.Strings.String.
Require Import PL.RTClosure.
Local Open Scope Z.
Local Open Scope string.
Require Import Coq.Strings.String.
Require Import PL.RTClosure.
Local Open Scope Z.
Local Open Scope string.
Lambda Expressions
- For C++: https://www.onlinegdb.com/online_c++_compiler .
- For Ocaml: https://www.jdoodle.com/compile-ocaml-online .
- Python: https://www.tutorialspoint.com/execute_python_online.php.
// C++ #include <functional> #include <iostream> template <typename T> std::function<T(T)> do_it_three_times (std::function<T(T)> f) { return [f](T x) { return f(f(f(x))); }; } int main() { std::function<int(int)> add_one = [](int x) {return x + 1; }; std::function<int(int)> square = [](int x) {return x * x; }; std::cout << do_it_three_times (add_one) (1); std::cout << std::endl; std::cout << do_it_three_times (square) (2); std::cout << std::endl; std::cout << do_it_three_times (do_it_three_times(add_one)) (0); std::cout << std::endl; // The following line does not work for C++, // because do_it_three_times is a function not an object // std::cout << do_it_three_times (do_it_three_times) (add_one) (0); std::function<std::function<int(int)>(std::function<int(int)>)> do_it_three_times_obj = [](std::function<int(int)> f) {return do_it_three_times (f); }; std::cout << do_it_three_times (do_it_three_times_obj) (add_one) (0); std::cout << std::endl; }
(* Ocaml *) let do_it_three_times f x = f (f (f x)) in let add_one x = x + 1 in let square x = x * x in Printf.printf "%d\n" (do_it_three_times add_one 1); Printf.printf "%d\n" (do_it_three_times square 2); Printf.printf "%d\n" (do_it_three_times (do_it_three_times add_one) 0); Printf.printf "%d\n" (do_it_three_times do_it_three_times add_one 0);
# Python do_it_three_times = lambda f : lambda x : f (f (f (x))) add_one = lambda x : x + 1 square = lambda x : x * x print (do_it_three_times (add_one) (1)) print "\n" print (do_it_three_times (square) (2)) print "\n" print (do_it_three_times (do_it_three_times (add_one)) (0)) print "\n" print (do_it_three_times (do_it_three_times) (add_one) (0)) print "\n"
Inductive op : Type :=
| Oplus
| Ominus
| Omult
| Oeq
| Ole
| Onot
| Oand
| Oifthenelse.
Inductive constant : Type :=
| int_const (n: Z): constant
| bool_const (b: bool): constant
| op_const (o: op): constant.
Inductive tm : Type :=
| var : string -> tm
| app : tm -> tm -> tm
| abs : string -> tm -> tm
| con : constant -> tm.
| Oplus
| Ominus
| Omult
| Oeq
| Ole
| Onot
| Oand
| Oifthenelse.
Inductive constant : Type :=
| int_const (n: Z): constant
| bool_const (b: bool): constant
| op_const (o: op): constant.
Inductive tm : Type :=
| var : string -> tm
| app : tm -> tm -> tm
| abs : string -> tm -> tm
| con : constant -> tm.
Here, abs means function abstraction and app means function application.
Coercion var: string >-> tm.
Coercion op_const: op >-> constant.
Coercion bool_const: bool >-> constant.
Coercion int_const: Z >-> constant.
Coercion con: constant >-> tm.
Example do_it_three_times: tm :=
abs "f" (abs "x" (app "f" (app "f" (app "f" "x")))).
Example add_one: tm :=
abs "x" (app (app Oplus "x") 1).
Example square: tm :=
abs "x" (app (app Omult "x") "x").
Example DITT_ex_1: tm :=
app (app do_it_three_times add_one) 1.
Example DITT_ex_2: tm :=
app (app do_it_three_times square) 2.
Example DITT_ex_3: tm :=
app (app do_it_three_times (app do_it_three_times add_one)) 0.
Example DITT_ex_4: tm :=
app (app (app do_it_three_times do_it_three_times) add_one) 0.
Coercion op_const: op >-> constant.
Coercion bool_const: bool >-> constant.
Coercion int_const: Z >-> constant.
Coercion con: constant >-> tm.
Example do_it_three_times: tm :=
abs "f" (abs "x" (app "f" (app "f" (app "f" "x")))).
Example add_one: tm :=
abs "x" (app (app Oplus "x") 1).
Example square: tm :=
abs "x" (app (app Omult "x") "x").
Example DITT_ex_1: tm :=
app (app do_it_three_times add_one) 1.
Example DITT_ex_2: tm :=
app (app do_it_three_times square) 2.
Example DITT_ex_3: tm :=
app (app do_it_three_times (app do_it_three_times add_one)) 0.
Example DITT_ex_4: tm :=
app (app (app do_it_three_times do_it_three_times) add_one) 0.
Operational Semantics
- app (abs x t1) t2 --> t1 [x ⟼ t2] .
- The function part should evaluated first. In other words, if t1 steps to
t1', then app t1 t2 steps to app t1' t2.
- When the function part is already evaluated (e.g. t1 = abs x t1', and
t1 = con (op_const Oplus)) and the argument part needs to be evaluated
(i.e. tm_pend t1), then the argument part will be evaluated. In other
words, if tm_pend t1 and step t2 t2', then step (app t1 t2) (app t1
t2').
- If both function part t1 and argument part t2 are evaluated, then
app t1 t2 will be reduced to the result of function application.
- If the function part t1 are evaluated and its argument part t2 does not need to be evaluated, then app t1 t2 will be directly reduced to this function application's result.
Inductive tm_base_halt: tm -> Prop :=
| BH_plus: ∀n: Z, tm_base_halt (app Oplus n)
| BH_minus: ∀n: Z, tm_base_halt (app Ominus n)
| BH_mult: ∀n: Z, tm_base_halt (app Omult n)
| BH_eq: ∀n: Z, tm_base_halt (app Oeq n)
| BH_le: ∀n: Z, tm_base_halt (app Ole n)
| BH_and: ∀b: bool, tm_base_halt (app Oand b)
| BH_if1: ∀b: bool, tm_base_halt (app Oifthenelse b)
| BH_if2: ∀(b: bool) (t: tm), tm_base_halt (app (app Oifthenelse b) t).
Inductive tm_base_pend: tm -> Prop :=
| BP_plus: ∀n: Z, tm_base_pend (app Oplus n)
| BP_minus: ∀n: Z, tm_base_pend (app Ominus n)
| BP_mult: ∀n: Z, tm_base_pend (app Omult n)
| BP_eq: ∀n: Z, tm_base_pend (app Oeq n)
| BP_le: ∀n: Z, tm_base_pend (app Ole n)
| BP_and_true: tm_base_pend (app Oand true).
Inductive tm_halt: tm -> Prop :=
| H_abs: ∀x t, tm_halt (abs x t)
| H_con: ∀c, tm_halt (con c)
| H_base: ∀t, tm_base_halt t -> tm_halt t.
Inductive tm_pend: tm -> Prop :=
| P_abs: ∀x t, tm_pend (abs x t)
| P_con: ∀c, tm_pend (con c)
| P_base: ∀t, tm_base_pend t -> tm_pend t.
Inductive base_step: tm -> tm -> Prop :=
| BS_plus: ∀n1 n2: Z, base_step (app (app Oplus n1) n2) (n1 + n2)
| BS_minus: ∀n1 n2: Z, base_step (app (app Ominus n1) n2) (n1 - n2)
| BS_mult: ∀n1 n2: Z, base_step (app (app Omult n1) n2) (n1 * n2)
| BS_eq_true: ∀n1 n2: Z,
n1 = n2 -> base_step (app (app Oeq n1) n2) (true)
| BS_eq_false: ∀n1 n2: Z,
n1 ≠ n2 -> base_step (app (app Oeq n1) n2) (false)
| BS_le_true: ∀n1 n2: Z,
n1 ≤ n2 -> base_step (app (app Ole n1) n2) (true)
| BS_le_false: ∀n1 n2: Z,
n1 > n2 -> base_step (app (app Ole n1) n2) (false)
| BS_not: ∀b: bool, base_step (app Onot b) (negb b)
| BS_and_true: ∀b: bool, base_step (app (app Oand true) b) b
| BS_and_false: ∀t: tm, base_step (app (app Oand false) t) false
| BS_if_true: ∀t1 t2: tm,
base_step (app (app (app Oifthenelse true) t1) t2) t1
| BS_if_false: ∀t1 t2: tm,
base_step (app (app (app Oifthenelse false) t1) t2) t2
.
Fixpoint subst (x : string) (s : tm) (t : tm) : tm :=
match t with
| var x' ⇒
if string_dec x x' then s else t
| abs x' t1 ⇒
abs x' (if string_dec x x' then t1 else subst x s t1)
| app t1 t2 ⇒
app (subst x s t1) (subst x s t2)
| con c ⇒
con c
end.
Notation "t [ x ⟼ s ]" := (subst x s t) (at level 10, x at next level).
Inductive step: tm -> tm -> Prop :=
| S_base: ∀t t',
base_step t t' -> step t t'
| S_beta: ∀x t1 t2,
tm_halt t2 -> step (app (abs x t1) t2) (t1 [ x ⟼ t2])
| S_app1: ∀t1 t1' t2,
step t1 t1' -> step (app t1 t2) (app t1' t2)
| S_app2: ∀t1 t2 t2',
tm_pend t1 -> step t2 t2' -> step (app t1 t2) (app t1 t2')
.
Example DITT_result_1:
clos_refl_trans step
(app (app do_it_three_times add_one) 1)
4.
| BH_plus: ∀n: Z, tm_base_halt (app Oplus n)
| BH_minus: ∀n: Z, tm_base_halt (app Ominus n)
| BH_mult: ∀n: Z, tm_base_halt (app Omult n)
| BH_eq: ∀n: Z, tm_base_halt (app Oeq n)
| BH_le: ∀n: Z, tm_base_halt (app Ole n)
| BH_and: ∀b: bool, tm_base_halt (app Oand b)
| BH_if1: ∀b: bool, tm_base_halt (app Oifthenelse b)
| BH_if2: ∀(b: bool) (t: tm), tm_base_halt (app (app Oifthenelse b) t).
Inductive tm_base_pend: tm -> Prop :=
| BP_plus: ∀n: Z, tm_base_pend (app Oplus n)
| BP_minus: ∀n: Z, tm_base_pend (app Ominus n)
| BP_mult: ∀n: Z, tm_base_pend (app Omult n)
| BP_eq: ∀n: Z, tm_base_pend (app Oeq n)
| BP_le: ∀n: Z, tm_base_pend (app Ole n)
| BP_and_true: tm_base_pend (app Oand true).
Inductive tm_halt: tm -> Prop :=
| H_abs: ∀x t, tm_halt (abs x t)
| H_con: ∀c, tm_halt (con c)
| H_base: ∀t, tm_base_halt t -> tm_halt t.
Inductive tm_pend: tm -> Prop :=
| P_abs: ∀x t, tm_pend (abs x t)
| P_con: ∀c, tm_pend (con c)
| P_base: ∀t, tm_base_pend t -> tm_pend t.
Inductive base_step: tm -> tm -> Prop :=
| BS_plus: ∀n1 n2: Z, base_step (app (app Oplus n1) n2) (n1 + n2)
| BS_minus: ∀n1 n2: Z, base_step (app (app Ominus n1) n2) (n1 - n2)
| BS_mult: ∀n1 n2: Z, base_step (app (app Omult n1) n2) (n1 * n2)
| BS_eq_true: ∀n1 n2: Z,
n1 = n2 -> base_step (app (app Oeq n1) n2) (true)
| BS_eq_false: ∀n1 n2: Z,
n1 ≠ n2 -> base_step (app (app Oeq n1) n2) (false)
| BS_le_true: ∀n1 n2: Z,
n1 ≤ n2 -> base_step (app (app Ole n1) n2) (true)
| BS_le_false: ∀n1 n2: Z,
n1 > n2 -> base_step (app (app Ole n1) n2) (false)
| BS_not: ∀b: bool, base_step (app Onot b) (negb b)
| BS_and_true: ∀b: bool, base_step (app (app Oand true) b) b
| BS_and_false: ∀t: tm, base_step (app (app Oand false) t) false
| BS_if_true: ∀t1 t2: tm,
base_step (app (app (app Oifthenelse true) t1) t2) t1
| BS_if_false: ∀t1 t2: tm,
base_step (app (app (app Oifthenelse false) t1) t2) t2
.
Fixpoint subst (x : string) (s : tm) (t : tm) : tm :=
match t with
| var x' ⇒
if string_dec x x' then s else t
| abs x' t1 ⇒
abs x' (if string_dec x x' then t1 else subst x s t1)
| app t1 t2 ⇒
app (subst x s t1) (subst x s t2)
| con c ⇒
con c
end.
Notation "t [ x ⟼ s ]" := (subst x s t) (at level 10, x at next level).
Inductive step: tm -> tm -> Prop :=
| S_base: ∀t t',
base_step t t' -> step t t'
| S_beta: ∀x t1 t2,
tm_halt t2 -> step (app (abs x t1) t2) (t1 [ x ⟼ t2])
| S_app1: ∀t1 t1' t2,
step t1 t1' -> step (app t1 t2) (app t1' t2)
| S_app2: ∀t1 t2 t2',
tm_pend t1 -> step t2 t2' -> step (app t1 t2) (app t1 t2')
.
Example DITT_result_1:
clos_refl_trans step
(app (app do_it_three_times add_one) 1)
4.
Informally,
do_it_three_times add_one =
(fun f x ⇒ f (f (f x))) add_one 1 ⇒
(fun x ⇒ add_one (add_one (add_one x))) 1 ⇒
add_one (add_one (add_one 1)) =
add_one (add_one ((fun x ⇒ x + 1) 1)) ⇒
add_one (add_one (1 + 1)) ⇒
add_one (add_one 2) =
add_one ((fun x ⇒ x + 1) 2) ⇒
add_one (2 + 1) ⇒
add_one 3 =
(fun x ⇒ x + 1) 3 ⇒
3 + 1 ⇒
4
(fun f x ⇒ f (f (f x))) add_one 1 ⇒
(fun x ⇒ add_one (add_one (add_one x))) 1 ⇒
add_one (add_one (add_one 1)) =
add_one (add_one ((fun x ⇒ x + 1) 1)) ⇒
add_one (add_one (1 + 1)) ⇒
add_one (add_one 2) =
add_one ((fun x ⇒ x + 1) 2) ⇒
add_one (2 + 1) ⇒
add_one 3 =
(fun x ⇒ x + 1) 3 ⇒
3 + 1 ⇒
4
Proof.
unfold do_it_three_times, add_one.
etransitivity_1n.
{ apply S_app1. apply S_beta. apply H_abs. }
simpl subst.
etransitivity_1n.
{ apply S_beta. apply H_con. }
simpl subst.
etransitivity_1n.
{
apply S_app2; [apply P_abs |].
apply S_app2; [apply P_abs |].
apply S_beta.
apply H_con.
}
simpl subst.
etransitivity_1n.
{
apply S_app2; [apply P_abs |].
apply S_app2; [apply P_abs |].
apply S_base.
apply BS_plus.
}
simpl Z.add.
simpl subst.
etransitivity_1n.
{
apply S_app2; [apply P_abs |].
apply S_beta.
apply H_con.
}
simpl subst.
etransitivity_1n.
{
apply S_app2; [apply P_abs |].
apply S_base.
apply BS_plus.
}
simpl Z.add.
etransitivity_1n.
{ apply S_beta. apply H_con. }
simpl subst.
etransitivity_1n.
{ apply S_base. apply BS_plus. }
simpl Z.add.
reflexivity.
Qed.
(* 2021-05-17 00:32 *)
unfold do_it_three_times, add_one.
etransitivity_1n.
{ apply S_app1. apply S_beta. apply H_abs. }
simpl subst.
etransitivity_1n.
{ apply S_beta. apply H_con. }
simpl subst.
etransitivity_1n.
{
apply S_app2; [apply P_abs |].
apply S_app2; [apply P_abs |].
apply S_beta.
apply H_con.
}
simpl subst.
etransitivity_1n.
{
apply S_app2; [apply P_abs |].
apply S_app2; [apply P_abs |].
apply S_base.
apply BS_plus.
}
simpl Z.add.
simpl subst.
etransitivity_1n.
{
apply S_app2; [apply P_abs |].
apply S_beta.
apply H_con.
}
simpl subst.
etransitivity_1n.
{
apply S_app2; [apply P_abs |].
apply S_base.
apply BS_plus.
}
simpl Z.add.
etransitivity_1n.
{ apply S_beta. apply H_con. }
simpl subst.
etransitivity_1n.
{ apply S_base. apply BS_plus. }
simpl Z.add.
reflexivity.
Qed.
(* 2021-05-17 00:32 *)