2024-12-01 18:06:03 -08:00
|
|
|
@include logic.pg
|
|
|
|
|
|
2024-11-20 07:37:57 -08:00
|
|
|
-- 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
|
2024-12-10 23:36:34 -08:00
|
|
|
-- `A → A` and repeating it `n` times
|
|
|
|
|
def nat : ★ := forall (A : ★), (A → A) → A → A;
|
2024-11-20 07:37:57 -08:00
|
|
|
|
|
|
|
|
-- zero is the constant function
|
2024-12-10 23:36:34 -08:00
|
|
|
def zero : nat := fun (A : ★) (f : A → A) (x : A) => x;
|
2024-11-20 07:37:57 -08:00
|
|
|
|
|
|
|
|
-- `suc n` composes one more `f` than `n`
|
2024-12-10 23:36:34 -08:00
|
|
|
def suc : nat → nat := fun (n : nat) (A : ★) (f : A → A) (x : A) => f ((n A f) x);
|
2024-11-20 07:37:57 -08:00
|
|
|
|
|
|
|
|
-- addition can be encoded as usual
|
2024-12-10 23:36:34 -08:00
|
|
|
def + : nat → nat → nat := fun (n m : nat) (A : ★) (f : A → A) (x : A) => (m A f) (n A f x);
|
2024-12-10 20:31:53 -08:00
|
|
|
infixl 20 +;
|
2024-11-20 07:37:57 -08:00
|
|
|
|
|
|
|
|
-- likewise for multiplication
|
2024-12-10 23:36:34 -08:00
|
|
|
def * : nat → nat → nat := fun (n m : nat) (A : ★) (f : A → A) (x : A) => (m A (n A f)) x;
|
2024-12-10 20:31:53 -08:00
|
|
|
infixl 30 *;
|
2024-11-20 07:37:57 -08:00
|
|
|
|
|
|
|
|
-- 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
|
2024-11-30 23:43:17 -08:00
|
|
|
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;
|
2024-11-20 07:37:57 -08:00
|
|
|
|
2024-12-10 20:31:53 -08:00
|
|
|
def = (n m : nat) := eq nat n m;
|
|
|
|
|
infixl 1 =;
|
|
|
|
|
|
2024-11-20 07:37:57 -08:00
|
|
|
-- now we can do a bunch of computations, even at the type level
|
|
|
|
|
-- the way we can do this is by defining equality (see <examples/logic.pg> for
|
|
|
|
|
-- more details on how this works) and proving a bunch of theorems like
|
2024-12-10 20:31:53 -08:00
|
|
|
-- `one + one = two` (how exciting!)
|
2024-11-20 07:37:57 -08:00
|
|
|
-- 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`
|
2024-12-10 20:31:53 -08:00
|
|
|
def one_plus_one_is_two : one + one = two := eq_refl nat two;
|
2024-11-20 07:37:57 -08:00
|
|
|
|
|
|
|
|
-- we can likewise compute 2 + 2
|
2024-12-10 20:31:53 -08:00
|
|
|
def two_plus_two_is_four : two + two = four := eq_refl nat four;
|
2024-11-20 07:37:57 -08:00
|
|
|
|
|
|
|
|
-- even multiplication works
|
2024-12-10 20:31:53 -08:00
|
|
|
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;
|