I wish all types (type families) in the standard library came with a distinguished notions of validity and equivalence, ideally expressed using a partial equivalence relations. For example
nat_per := Logic.eq
prod_per {A B} A_per B_per := fun '(x1, y1) '(x2, y2) => A_per x2 x2 /\ B_per y1 y2
Q_per := fun '(n1, d1) '(n2, d2) => d1 <> 0 /\ d2 <> 0 /\ n1*d2 /\ n2*d1
option_per {T} T_per := fun a b => match a, b with Some x, Some y => T_per x y | None, None => True | _ => False end.
Prop_per := iff
proof_per (P : Prop) := fun pf1 pf2 : P => True
int_per := fun a b => pair_per _ _ (nat_and_sign_of_int a) (nat_and_sign_of_int b)
All this would be proven symmetric and transitive, and also reflexive if they are.
I wish all types (type families) in the standard library came with a distinguished notions of validity and equivalence, ideally expressed using a partial equivalence relations. For example
nat_per := Logic.eqprod_per {A B} A_per B_per := fun '(x1, y1) '(x2, y2) => A_per x2 x2 /\ B_per y1 y2Q_per := fun '(n1, d1) '(n2, d2) => d1 <> 0 /\ d2 <> 0 /\ n1*d2 /\ n2*d1option_per {T} T_per := fun a b => match a, b with Some x, Some y => T_per x y | None, None => True | _ => False end.Prop_per := iffproof_per (P : Prop) := fun pf1 pf2 : P => Trueint_per := fun a b => pair_per _ _ (nat_and_sign_of_int a) (nat_and_sign_of_int b)All this would be proven symmetric and transitive, and also reflexive if they are.