diff --git a/_CoqProject b/_CoqProject index 2fdb39c70834286abb38f3a3de0ad68773e99ee1..2c69aa50d476fa7efe13c3a39f94f0e913d3e38e 100644 --- a/_CoqProject +++ b/_CoqProject @@ -40,4 +40,5 @@ theories/functions.v theories/hlist.v theories/sorting.v theories/infinite.v +theories/nat_cancel.v diff --git a/theories/nat_cancel.v b/theories/nat_cancel.v new file mode 100644 index 0000000000000000000000000000000000000000..97f5437623839f71e2470a061611ea98f0101797 --- /dev/null +++ b/theories/nat_cancel.v @@ -0,0 +1,86 @@ +From stdpp Require Import numbers. + +(* The class [NatCancel m n m' n'] is a simple canceler for natural numbers +implemented using type classes. + +Input: [m], [n]; output: [m'], [n']. + +It turns an equality [n = m] into an equality [n' = m'] by canceling out terms +that appear on both sides of the equality. We provide instances to handle the +following connectives over natural numbers: + + n := 0 | t | n + m | S m + +Here, [t] represents arbitrary terms that do not fit the grammar. The instances +the class perform a depth-first traversal (from left to right) through [n] and +try to cancel each leaf in [m]. This implies that the shape of the original +expressions [n] and [m] are preserved as much as possible. For example, +canceling: + + S (S m2) + (k1 + (S k2 + k3)) + n1 = 2 + S ((n1 + S n2) + S (S m1 + m2)) + +Results in: + + k1 + (k2 + k3) = S (n2 + S (S m1)) + +The instances are setup up so that canceling is performed in two stages. + +- In the first stage, using the class [NatCancel], it traverses [m] w.r.t. [S] + and [+]. +- In the second stage, for each leaf (i.e. a constant or arbitrary term) + obtained by the traversal in stage 1, it uses the class [NatCancelLeaf] to + cancel the leaf in [n]. + +Be warned: Since the canceler is implemented using type classes it should only +be used it either of the inputs is relatively small. For bigger inputs, an +approach based on reflection would be better, but for small inputs, the overhead +of reification will probably not be worth it. *) +Class NatCancel (m n m' n' : nat) := nat_cancel : m' + n = m + n'. +Hint Mode NatCancel ! ! - - : typeclass_instances. +Class NatCancelLeaf (m n m' n' : nat) := nat_cancel_leaf : NatCancel m n m' n'. +Hint Mode NatCancelLeaf ! ! - - : typeclass_instances. + +Global Existing Instance nat_cancel_leaf | 100. + +Class MakeNatS (n1 n2 m : nat) := make_nat_S : m = n1 + n2. +Global Instance make_nat_S_0_l n : MakeNatS 0 n n. +Proof. done. Qed. +Global Instance make_nat_S_1 n : MakeNatS 1 n (S n). +Proof. done. Qed. + +Class MakeNatPlus (n1 n2 m : nat) := make_nat_plus : m = n1 + n2. +Global Instance make_nat_plus_0_l n : MakeNatPlus 0 n n. +Proof. done. Qed. +Global Instance make_nat_plus_0_r n : MakeNatPlus n 0 n. +Proof. unfold MakeNatPlus. by rewrite Nat.add_0_r. Qed. +Global Instance make_nat_plus_default n1 n2 : MakeNatPlus n1 n2 (n1 + n2) | 100. +Proof. done. Qed. + +Global Instance nat_cancel_leaf_here m : NatCancelLeaf m m 0 0 | 0. +Proof. by unfold NatCancelLeaf, NatCancel. Qed. +Global Instance nat_cancel_leaf_else m n : NatCancelLeaf m n m n | 100. +Proof. by unfold NatCancelLeaf, NatCancel. Qed. +Global Instance nat_cancel_leaf_plus m m' m'' n1 n2 n1' n2' n1'n2' : + NatCancelLeaf m n1 m' n1' → NatCancelLeaf m' n2 m'' n2' → + MakeNatPlus n1' n2' n1'n2' → NatCancelLeaf m (n1 + n2) m'' n1'n2' | 2. +Proof. unfold NatCancelLeaf, NatCancel, MakeNatPlus. omega. Qed. +Global Instance nat_cancel_leaf_S_here m n m' n' : + NatCancelLeaf m n m' n' → NatCancelLeaf (S m) (S n) m' n' | 3. +Proof. unfold NatCancelLeaf, NatCancel. omega. Qed. +Global Instance nat_cancel_leaf_S_else m n m' n' : + NatCancelLeaf m n m' n' → NatCancelLeaf m (S n) m' (S n') | 4. +Proof. unfold NatCancelLeaf, NatCancel. omega. Qed. + +(* The instance [nat_cancel_S_both] is redundant, but may reduce proof search +quite a bit, e.g. when canceling constants in constants. *) +Global Instance nat_cancel_S_both m n m' n' : + NatCancel m n m' n' → NatCancel (S m) (S n) m' n' | 1. +Proof. unfold NatCancel. omega. Qed. +Global Instance nat_cancel_plus m1 m2 m1' m2' m1'm2' n n' n'' : + NatCancel m1 n m1' n' → NatCancel m2 n' m2' n'' → + MakeNatPlus m1' m2' m1'm2' → NatCancel (m1 + m2) n m1'm2' n'' | 2. +Proof. unfold NatCancel, MakeNatPlus. omega. Qed. +Global Instance nat_cancel_S m m' m'' Sm' n n' n'' : + NatCancel m n m' n' → NatCancelLeaf 1 n' m'' n'' → + MakeNatS m'' m' Sm' → NatCancel (S m) n Sm' n'' | 3. +Proof. unfold NatCancelLeaf, NatCancel, MakeNatS. omega. Qed. \ No newline at end of file