I am trying to use a formal logic system I recently implemented in Coq to study ZF set theory. In order to do this, I need to define a type representing the domain in question, and then prove that each axiom holds in that context. The problem is, I'm getting stuck on the first of those steps.
My definition is as follows:
Inductive ZFSet : Type :=
| sup : forall (A : Type), (A -> ZFSet) -> ZFSet.
Fixpoint ZFEq (S T : ZFSet) : Prop :=
match S, T with
| sup A f, sup B g =>
(forall a, exists b, ZFEq (f a) (g b)) /\
(forall b, exists a, ZFEq (f a) (g b))
end.
Definition ZFIn E S : Prop :=
match S with
| sup A f => exists a, ZFEq E (f a)
end.
Since the formal logic system needs to support predicates of arbitrary arity, I have defined:
Definition zf_in (a : Vector.t ZFSet 2) : Prop :=
Vector.caseS' a (const Prop) (fun e a =>
Vector.caseS' a (const Prop) (fun x a =>
Vector.case0 (const Prop) (ZFIn e x) a))
so that ZFIn e x <-> zf_in [e; x]
. I know that case0
is redundant, but it feels neater to me, and I doubt it will affect the core issue.
The trouble is, I need to prove that zf_in
is compatible with ZFEq
as an equivalence relation. In my system, that means proving:
Lemma zf_in_wd : forall (a b : Vector.t ZFSet 2),
Vector.Forall2 ZFEq a b -> zf_in a -> zf_in b
I have already managed to prove:
Lemma ZFIn_wd : forall (e e' x x' : ZFSet), ZFEq e e' -> ZFEq x x' -> ZFIn e x -> ZFIn e' x'.
The problem is in closing the gap between these two Lemma
s. I cannot figure out how to deconstruct the Vector.Forall2 ZFSet 2
object. Note that I can deconstruct the Vector ZFSet 2
objects into a fixed collection of variables just fine; it is only the Vector.Forall2 ZFSet 2
which is causing trouble.
I have tried the following tactics on a hypothesis named E
, which generated the indicated errors:
inversion E
:
Illegal application: The term "sigT" of type "forall A : Type, (A -> Type) -> Type" cannot be applied to the terms "nat" : "Set" "fun n : nat => Vector.t ZFSet n" : "nat -> Type" The 2nd term has type "nat -> Type@{max(Set,ZFSet.u0+1)}" which should be coercible to "nat -> Type@{sigT.u1}".
dependent destruction E
:
Illegal application: The term "JMeq" of type "forall A : Type, A -> forall B : Type, B -> Prop" cannot be applied to the terms "Vector.t ZFSet n" : "Type" "gen_x" : "Vector.t ZFSet n" "Vector.t ZFSet 2" : "Type" "Vector.cons ZFSet ea 1 (Vector.cons ZFSet xa 0 (Vector.nil ZFSet))" : "Vector.t ZFSet 2" The 1st term has type "Type@{max(Set,ZFSet.u0+1)}" which should be coercible to "Type@{JMeq.u0}".
dependent induction E
: same asdependent destruction
apply Vector.Forall2_nth_order in E
:
Unable to apply lemma of type "forall (A : Type) (P : A -> A -> Prop) (n : nat) (v1 v2 : VectorDef.t A n), VectorDef.Forall2 P v1 v2 <-> (forall (i : nat) (Hi1 Hi2 : i < n), P (VectorDef.nth_order v1 Hi1) (VectorDef.nth_order v2 Hi2))" on hypothesis of type "Vector.Forall2 ZFEq (Vector.cons ZFSet ea 1 (Vector.cons ZFSet xa 0 (Vector.nil ZFSet))) (Vector.cons ZFSet eb 1 (Vector.cons ZFSet xb 0 (Vector.nil ZFSet)))".
pose proof (proj1 (Vector.Forall2_nth_order ZFSet ZFEq 2 _ _) E)
:
In environment ea, xa, eb, xb : ZFSet E : Vector.Forall2 ZFEq (Vector.cons ZFSet ea 1 (Vector.cons ZFSet xa 0 (Vector.nil ZFSet))) (Vector.cons ZFSet eb 1 (Vector.cons ZFSet xb 0 (Vector.nil ZFSet))) I : zf_set_interp 2 set_in_p (Vector.cons ZFSet ea 1 (Vector.cons ZFSet xa 0 (Vector.nil ZFSet))) The term "ZFSet" has type "Type@{ZFSet.u0+1}" while it is expected to have type "Type@{Vector.Forall2_nth_order.u0}" (universe inconsistency: Cannot enforce ZFSet.u0 < Vector.Forall2_nth_order.u0 because Vector.Forall2_nth_order.u0 <= ZFSet.u0).
I believe that the last error message is most telling of the problem here. I'm not deeply familiar with the workings of the Coq universe, so I don't know where the constraint Vector.Forall2_nth_order.u0 <= ZFSet.u0
is coming from. If possible, I would like to know a solution that does not involve rewriting my formal logic system to use a custom, universe polymorphic copy of the Vector
library. Thanks in advance!
Update
I've tracked down the source of the error by copy-pasting a minimal reproducible example. It worked fine directly under the definitions, but not down the file. The problem is in another definition:
Definition ZFUnion (x : ZFSet) : ZFSet.
Proof.
destruct x as [A f].
apply sup with (A := sigT A (fun a => match f a with sup B _ => B end)).
intros [a b]. destruct (f a) as [B g]. exact (g b).
Defined.
which puts a constraint between sigT
and ZFSet
. This seems to be the root cause of all the problems. The neatest solution I can think of is making a duplicate of sigT
for this one definition. This sort of issue seems to be the exact reason that Universe Polymorphism exists, but it's not applied to the standard library since it's still experimental.
Context (function predicate : nat -> Type)
, so that anyType
can be used to represent the class of $n$-ary functions and/or predicates. The language is built up from that, with things likeInductive term : Type := | tvar : nat -> term | tfunc : forall n, function n -> Vector.t term n -> term.
$\endgroup$domain : Type
, as well asfunction_interp : forall n, function n -> Vector.t domain n -> domain
andpredicate_interp : forall n, predicate n -> Vector.t domain n -> Prop
. This is done relative to an arbitrary equivalence relation, in this caseZFEq
. More required parameters contain evidence for the independence of representative. $\endgroup$n
and then dealing withVector.t domain n
, use a type as arity, and havearity s -> domain
isntead. It's easier, it's slicker, you can do induction on them, etc. $\endgroup$