diff --git a/examples/and.mdln b/examples/and.mdln deleted file mode 100644 index d1b9a0d2db51fc63aef58fcee53af97a748dfa5f..0000000000000000000000000000000000000000 --- a/examples/and.mdln +++ /dev/null @@ -1,9 +0,0 @@ -def And: Prop -> Prop -> Prop := fun A B: Prop => (C: Prop) -> (A -> B -> C) -> C - -def And_intro := (A B: Prop) -> A -> B -> And A B -def And_elim_g := (A B: Prop) -> And A B -> A -def And_elim_d := (A B: Prop) -> And A B -> B - -def and_intro_lemma: And_intro := fun A B: Prop, a: A, b: B, C: Prop, f: A -> B -> C => f a b -def and_elim_g_lemma: And_elim_g := fun A B: Prop, f: And A B => f A (fun a: A, b: B => a) -def and_elim_d_lemma: And_elim_d := fun A B: Prop, f: And A B => f B (fun a: A, b: B => b) diff --git a/examples/contraposition.mdln b/examples/contraposition.mdln deleted file mode 100644 index f6a7aeefaaeec003b5cd415fe951ded0fdcea230..0000000000000000000000000000000000000000 --- a/examples/contraposition.mdln +++ /dev/null @@ -1,4 +0,0 @@ -def not: Prop -> Prop := fun P: Prop => P -> False - -def Contrapose := (A B: Prop) -> (A -> B) -> (not B -> not A) -def contrapose_lemma: Contrapose := fun A B: Prop, f: A -> B, nB: not B, a: A => nB (f a) diff --git a/examples/eq.mdln b/examples/eq.mdln index b9558aa43d58a9473c90cb7bc27af1a3a7dc2cfc..661c18226a1cee6e7da366845ab5497444a662d7 100644 --- a/examples/eq.mdln +++ b/examples/eq.mdln @@ -1,22 +1,3 @@ -def transport_type.{u,v} := (A : Sort u) -> (P : A -> Sort v) -> (x y : A) -> Eq.{u} A x y -> P x -> P y +import ../std/eq.mdln -def transport.{u,v} : transport_type.{u,v} := - fun A:Sort u,P:A -> Sort v,x y:A, p: Eq.{u} A x y,h:P x => - Eq_rec.{u,v} A x (fun y:A,p:Eq.{u} A x y => P y) h y p - -def transport_id.{u} := fun A:Sort u,x:A => transport.{u,u} A (fun x:A => A) x x (Refl.{u} A x) x - -def symm.{u} : (A : Sort u) -> (x y : A) -> Eq.{u} A x y -> Eq.{u} A y x := - fun A:Sort u, - x y: A, - e : Eq.{u} A x y => - Eq_rec.{u,0} A x (fun y:A, e:Eq.{u} A x y => Eq.{u} A y x) (Refl.{u} A x) y e - -def trans.{u} : (A : Sort u) -> (x y z : A) -> Eq.{u} A x y -> Eq.{u} A y z -> Eq.{u} A x z := - fun A: Sort u, - x y z : A, - e1 : Eq.{u} A x y, - e2 : Eq.{u} A y z => - Eq_rec.{u,0} A y (fun x:A,e:Eq.{u} A y x => Eq.{u} A x z) e2 x (symm.{u} A x y e1) - -check Refl.{1} Nat Zero : Eq.{1} Nat Zero (transport_id.{1} Nat Zero) \ No newline at end of file +check Refl.{1} Nat Zero : Eq.{1} Nat Zero (transport_id.{1} Nat Zero) diff --git a/examples/irrelevance.mdln b/examples/irrelevance.mdln index 56d399eab8caaf414f78bc6d3c5459b829766d00..0eca694e6cd50e6fd5944395eb83bb9f43d25792 100644 --- a/examples/irrelevance.mdln +++ b/examples/irrelevance.mdln @@ -1,9 +1,9 @@ -def True := False -> False +def myTrue := False -> False -def id.{u} := fun A:Sort u,x:A => x +def id.{u} := fun A: Sort u, x: A => x -def tt1 : True := id.{0} False +def tt1: myTrue := id.{0} False -def tt2 : True := fun h:False => False_rec.{0} (fun h:False => False) h +def tt2: myTrue := fun h: False => False_rec.{0} (fun h: False => False) h -check Refl.{0} True tt1 : Eq.{0} True tt1 tt2 \ No newline at end of file +check Refl.{0} myTrue tt1: Eq.{0} myTrue tt1 tt2 diff --git a/examples/nat_eq.mdln b/examples/nat_eq.mdln deleted file mode 100644 index 42ce6392e301232b06ebbe3e48964058b1a1b244..0000000000000000000000000000000000000000 --- a/examples/nat_eq.mdln +++ /dev/null @@ -1,28 +0,0 @@ -def id.{u} := fun A :Sort u,x:A => x - -def Not := fun A : Prop => A -> False -def True := False -> False -def tt : True := id.{0} False - -def transport_type.{u,v} := (A : Sort u) -> (P : A -> Sort v) -> (x y : A) -> Eq.{u} A x y -> P x -> P y - -def transport.{u,v} : transport_type.{u,v} := - fun A:Sort u, - P:A -> Sort v, - x y:A, - p: Eq.{u} A x y, - h:P x => - Eq_rec.{u,v} A x (fun y:A,p:Eq.{u} A x y => P y) h y p - -def cast.{u} : (A B : Sort u) -> Eq.{u+1} (Sort u) A B -> A -> B := - fun A B : Sort u, - e : Eq.{u+1} (Sort u) A B, - a : A => - transport.{u+1,u} (Sort u) (fun A:Sort u => A) A B e a - -def is_zero := Nat_rec.{1} (fun n:Nat => Prop) True (fun n:Nat, p:Prop => False) - -def z_neq_s : (n: Nat) -> Not (Eq.{1} Nat Zero (Succ n)):= - fun n: Nat, - e : Eq.{1} Nat Zero (Succ n) => - transport.{1,0} Nat is_zero Zero (Succ n) e tt \ No newline at end of file diff --git a/proost/src/main.rs b/proost/src/main.rs index 02641c3ed26116e6c35cb749ee087d5e16463785..b9213f5abd932b51a58561ae389f52a5a2a38f71 100644 --- a/proost/src/main.rs +++ b/proost/src/main.rs @@ -104,7 +104,7 @@ fn main() -> Result<'static, 'static, ()> { // check if files are provided as command-line arguments if !args.files.is_empty() { - return kernel::memory::arena::use_arena(|arena| { + return kernel::memory::arena::use_arena_with_axioms(|arena| { let command = Command::Import(args.files.iter().map(|file| (Location::default(), file.as_str())).collect()); display(evaluator.process_line(arena, &command), false); diff --git a/std/eq.mdln b/std/eq.mdln new file mode 100644 index 0000000000000000000000000000000000000000..73452b99c46b31988c2dfbf92f5822df38622e0d --- /dev/null +++ b/std/eq.mdln @@ -0,0 +1,30 @@ +def transport_type.{u, v} := (A: Sort u) -> (P: A -> Sort v) -> (x y: A) -> Eq.{u} A x y -> P x -> P y + +def transport.{u, v}: transport_type.{u, v} := + fun A: Sort u, + P: A -> Sort v, + x y: A, + p: Eq.{u} A x y, + h: P x => + Eq_rec.{u, v} A x (fun y: A, p: Eq.{u} A x y => P y) h y p + +def transport_id.{u} := fun A: Sort u, x:A => transport.{u, u} A (fun x: A => A) x x (Refl.{u} A x) x + +def cast.{u}: (A B: Sort u) -> Eq.{u + 1} (Sort u) A B -> A -> B := + fun A B: Sort u, + e: Eq.{u + 1} (Sort u) A B, + a: A => + transport.{u + 1,u} (Sort u) (fun A: Sort u => A) A B e a + +def symm.{u}: (A: Sort u) -> (x y: A) -> Eq.{u} A x y -> Eq.{u} A y x := + fun A: Sort u, + x y: A, + e: Eq.{u} A x y => + Eq_rec.{u, 0} A x (fun y: A, e: Eq.{u} A x y => Eq.{u} A y x) (Refl.{u} A x) y e + +def trans.{u}: (A: Sort u) -> (x y z: A) -> Eq.{u} A x y -> Eq.{u} A y z -> Eq.{u} A x z := + fun A: Sort u, + x y z: A, + e1: Eq.{u} A x y, + e2: Eq.{u} A y z => + Eq_rec.{u, 0} A y (fun x:A, e:Eq.{u} A y x => Eq.{u} A x z) e2 x (symm.{u} A x y e1) diff --git a/std/nat.mdln b/std/nat.mdln new file mode 100644 index 0000000000000000000000000000000000000000..630f23ab51f8e0ea89e2949bcb6b508ec8bf5920 --- /dev/null +++ b/std/nat.mdln @@ -0,0 +1,9 @@ +import eq.mdln +import prop/connectives.mdln + +def is_zero := Nat_rec.{1} (fun n: Nat => Prop) True (fun n: Nat, p: Prop => False) + +def z_neq_s: (n: Nat) -> Not (Eq.{1} Nat Zero (Succ n)) := + fun n: Nat, + e: Eq.{1} Nat Zero (Succ n) => + transport.{1, 0} Nat is_zero Zero (Succ n) e Tt diff --git a/std/prop/classical.mdln b/std/prop/classical.mdln new file mode 100644 index 0000000000000000000000000000000000000000..4139c388b621d33cd09ef6a4f23b35c73de95782 --- /dev/null +++ b/std/prop/classical.mdln @@ -0,0 +1,106 @@ +// This file proves some lemmas on classical logic. + +import connectives.mdln +import false.mdln + +// The law of excluded middle. Note, this is a definition, not an +// assumption! If you want to prove a theorem in classical logic, +// formulate it as "Excluded_middle -> <what you want>". + +def Excluded_middle: Prop := (P: Prop) -> Or P (Not P) + +// The following proves that the following axioms are equivalent: +// Excluded_middle: (1) ∀P, P ∨ ¬P +// Double_negation_elimination: (2) ∀P, ¬¬P → P +// Implication_as_or: (3) ∀P,Q, (P → Q) → (¬P ∨ Q) +// Peirce: (4) ∀P,Q, ((P → Q) → P) → P +// Proof by: +// (1) => (2), (2) => (3), (3) => (1) +// (1) => (4), (4) => (1) + +def Double_negation_elimination: Prop := (P : Prop) -> ((Not (Not P)) -> P) + +def Implication_as_or: Prop := (P Q : Prop) -> (P -> Q) -> Or (Not P) Q + +def Peirce: Prop := (P Q: Prop) -> ((P -> Q) -> P) -> P + +// Lemmas (TODO: put in namespace when that works) +def excluded_middle_implies_double_negation_elimination: (Excluded_middle -> Double_negation_elimination) := + fun excl : Excluded_middle, P: Prop, notnotP : (Not (Not P)) => + (excl P) // Apply P \/ ~P + P // ... to prove P + (fun p: P => p) // P case: P -> P is trivial + // ~P case by contradiction with ~~P + (fun notP: (Not P) => + (exfalso P (notnotP notP))) + +def double_negation_elimination_implies_implication_as_or: (Double_negation_elimination -> Implication_as_or) := + (fun elim: Double_negation_elimination, P Q: Prop, PtoQ : (P -> Q) => + elim (Or (Not P) Q) // Prove ~P \/ Q by ~~(~P \/ Q) + (fun H: Not (Or (Not P) Q) => // Assume ~(~P \/ Q) and prove False + (fun p : P, qf: Not Q => qf (PtoQ p)) // From lemmas P and ~Q, prove False by P, P -> Q, Q -> False + (elim P // Prove P by ~~P + (fun HP: (Not P) => // Assume ~P, prove False + H (or_intro_l (Not P) Q HP))) // Deduce False from ~(~P \/ Q) + (fun q : Q => // Assume Q, prove False. + H (or_intro_r (Not P) Q q)))) // Deduce False from ~(~P \/ Q) + +def implication_as_or_implies_excluded_middle: Implication_as_or -> Excluded_middle := + (fun imp2or : Implication_as_or, P: Prop => // Let's prove ~P \/ P + or_comm (Not P) P // Trivially follows from P \/ ~P + (imp2or P P (fun p: P => p))) // P -> P, therefore ~P \/ P + +// Boilerplate: deduce (1) <=> (2) from (1) => (2) => (3) => (1) +def excluded_middle_iff_double_negation_elimination: Iff Excluded_middle Double_negation_elimination := + (iff_intro + Excluded_middle + Double_negation_elimination + excluded_middle_implies_double_negation_elimination + (fun elim: Double_negation_elimination => + implication_as_or_implies_excluded_middle + (double_negation_elimination_implies_implication_as_or elim))) + +// Boilerplate: deduce (1) <=> (3) from (1) => (2) => (3) => (1) +def excluded_middle_iff_implication_as_or: Iff Excluded_middle Implication_as_or := + (iff_intro + Excluded_middle + Implication_as_or + (fun excl: Excluded_middle => + double_negation_elimination_implies_implication_as_or + (excluded_middle_implies_double_negation_elimination excl)) + implication_as_or_implies_excluded_middle) + +def excluded_middle_implies_peirce: Excluded_middle -> Peirce := + (fun excl: Excluded_middle, P Q: Prop, H: ((P -> Q) -> P) => + (excl P) // Eliminate from P \/ ~P + P // To prove P + (fun p: P => p) // P -> P is trivial + // ~P -> P + (fun nP: Not P => + H // Prove P by H + // Need to prove P -> Q + (fun p: P => + // We have P and ~P, we can prove anything. + exfalso Q (nP p)))) + +def peirce_implies_excluded_middle: Peirce -> Excluded_middle := + (fun peirce: Peirce, P: Prop => + // Specialize Peirce's law: + // (((P \/ ~P) -> False) -> (P \/ ~P)) -> (P \/ ~P) + // Thus we can prove P \/ ~P by + // ((P \/ ~P) -> False) -> (P \/ ~P) + (peirce (Or P (Not P)) False) + (fun H: ((Or P (Not P)) -> False) => // assume (P \/ ~P) -> False + // We want to prove P \/ ~P. It suffices to prove ~P. + or_intro_r P (Not P) + // Prove ~P. + (fun p: P => // Assume P, deduce False + // We know P \/ ~P -> False, and we can prove + // P \/ ~P with P. + H (or_intro_l P (Not P) p)))) + +// Boilerplate: deduce (1) <=> (4) from (1) => (4) => (1) +def excluded_middle_iff_peirce: Iff Excluded_middle Peirce := + (iff_intro Excluded_middle Peirce + excluded_middle_implies_peirce + peirce_implies_excluded_middle) diff --git a/std/prop/connectives.mdln b/std/prop/connectives.mdln new file mode 100644 index 0000000000000000000000000000000000000000..088b576979614d9f19e82e7153ce1ed0c1c8c4f3 --- /dev/null +++ b/std/prop/connectives.mdln @@ -0,0 +1,38 @@ +// Basic logical connectives in Prop: and, or, not, iff + +// === And === +def And: Prop -> Prop -> Prop := fun A B: Prop => (C: Prop) -> (A -> B -> C) -> C + +def and_intro: (A B: Prop) -> A -> B -> And A B := + fun A B: Prop, a: A, b: B, C: Prop, f: A -> B -> C => f a b + +def and_elim_l: (A B: Prop) -> And A B -> A := + fun A B: Prop, f: And A B => f A (fun a: A, b: B => a) + +def and_elim_r: (A B: Prop) -> And A B -> B := + fun A B: Prop, f: And A B => f B (fun a: A, b: B => b) + +def and_comm: (A B: Prop) -> (And A B) -> (And B A) := + fun A B: Prop, f: (And A B), C: Prop, bac: (B -> A -> C) => f C (fun a:A, b:B => bac b a) + +// === Or === +def Or: Prop -> Prop -> Prop := fun A B : Prop => (C: Prop) -> (A -> C) -> (B -> C) -> C + +def or_intro_l : (A B : Prop) -> A -> Or A B := + fun A B: Prop, a: A, C: Prop, fAC: A -> C, fBC: B -> C => fAC a + +def or_intro_r : (A B : Prop) -> B -> Or A B := + fun A B: Prop, b: B, C: Prop, fAC: A -> C, fBC: B -> C => fBC b + +def or_comm: (A B : Prop) -> (Or A B) -> Or B A := + (fun A B: Prop, orAB: (Or A B), C: Prop, fBC: B -> C, fAC: A -> C => + orAB C fAC fBC) + +// === Not === +def Not: Prop -> Prop := fun P: Prop => P -> False + +// === Iff === +def Iff: Prop -> Prop -> Prop := fun P Q: Prop => And (P -> Q) (Q -> P) + +def iff_intro: (P Q: Prop) -> (P -> Q) -> (Q -> P) -> Iff P Q := + fun P Q: Prop, PQ: P -> Q, QP: Q -> P => and_intro (P -> Q) (Q -> P) PQ QP diff --git a/std/prop/contraposition.mdln b/std/prop/contraposition.mdln new file mode 100644 index 0000000000000000000000000000000000000000..bc4d63a97a5f22260577bf6c2aedaf06a7bba4e7 --- /dev/null +++ b/std/prop/contraposition.mdln @@ -0,0 +1,6 @@ +// Contraposition + +import connectives.mdln + +def contrapose: (A B: Prop) -> (A -> B) -> (Not B -> Not A) := + fun A B: Prop, f: A -> B, nB: (Not B), a: A => nB (f a) diff --git a/std/prop/false.mdln b/std/prop/false.mdln new file mode 100644 index 0000000000000000000000000000000000000000..678111e33eed864466ba565a54f38be082bfc491 --- /dev/null +++ b/std/prop/false.mdln @@ -0,0 +1,2 @@ +def exfalso: (P: Prop) -> False -> P := fun P: Prop, f: False => + False_rec.{0} (fun _: False => P) f