@include logic.pg -- without recursion, computation is kind of hard -- we can, however, define natural numbers using the Church encoding and do -- computation with them -- the natural number `n` is encoded as the function taking any function -- `A → A` and repeating it `n` times def nat : ★ := forall (A : ★), (A → A) → A → A; -- zero is the constant function def zero : nat := fun (A : ★) (f : A → A) (x : A) => x; -- `suc n` composes one more `f` than `n` def suc : nat → nat := fun (n : nat) (A : ★) (f : A → A) (x : A) => f ((n A f) x); -- addition can be encoded as usual def + : nat → nat → nat := fun (n m : nat) (A : ★) (f : A → A) (x : A) => (m A f) (n A f x); infixl 20 +; -- likewise for multiplication def * : nat → nat → nat := fun (n m : nat) (A : ★) (f : A → A) (x : A) => (m A (n A f)) x; infixl 30 *; -- unforunately, it is impossible to prove induction on Church numerals, -- which makes it really hard to prove standard theorems, or do anything really. -- but we can still do computations with Church numerals -- first some abbreviations for numbers will be handy def one : nat := suc zero; def two : nat := suc one; def three : nat := suc two; def four : nat := suc three; def five : nat := suc four; def six : nat := suc five; def seven : nat := suc six; def eight : nat := suc seven; def nine : nat := suc eight; def ten : nat := suc nine; def = (n m : nat) := eq nat n m; infixl 1 =; -- now we can do a bunch of computations, even at the type level -- the way we can do this is by defining equality (see for -- more details on how this works) and proving a bunch of theorems like -- `one + one = two` (how exciting!) -- then perga will only accept our proof if `plus one one` and `two` are beta -- equivalent -- since `plus one one` and `two` are beta-equivalent, `eq_refl nat two` is a -- proof that `1 + 1 = 2` def one_plus_one_is_two : one + one = two := eq_refl nat two; -- we can likewise compute 2 + 2 def two_plus_two_is_four : two + two = four := eq_refl nat four; -- even multiplication works def two_times_five_is_ten : two * five = ten := eq_refl nat ten; -- this is just to kind of show off the parser def mixed : two + four * two = ten := eq_refl nat ten;