perga/examples/computation.pg

55 lines
2.1 KiB
Text

@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 plus : nat -> nat -> nat := fun (n m : nat) (A : *) (f : A -> A) (x : A) => (m A f) (n A f x);
-- likewise for multiplication
def times : nat -> nat -> nat := fun (n m : nat) (A : *) (f : A -> A) (x : A) => (m A (n A f)) x;
-- 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;
-- 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
-- `plus 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 : eq nat (plus one one) two := eq_refl nat two;
-- we can likewise compute 2 + 2
def two_plus_two_is_four : eq nat (plus two two) four := eq_refl nat four;
-- even multiplication works
def two_times_five_is_ten : eq nat (times two five) ten := eq_refl nat ten;