Search code examples
coqforall

Coq convert non exist to forall statement


I'm new to Coq. Here's my problem. I have a statement says:

H : forall x : term, ~ (exists y : term, P x y /\ ~ P y x)

I guess it is equivalent to:

forall x y : term, (P x y /\ ~ P y x) -> false

But which tactic can I use to convert the hypothesis?


Solution

  • I don't know of a tactic to turn not-exists into forall-not, but you can always just assert and prove it. (If you need that repeatedly, you can pack that up into an Ltac tactic definition or a simple theorem[1].)

    Here's three ways of getting this proved. (You should be able to just copy/paste this transcript into CoqIDE or Emacs/ProofGeneral and step through the code.)

    [1] There exists a lemma not_ex_all_not in the Library Coq.Logic.Classical_Pred_Type, but loading that would pull in the axiom for classical logic (which isn't even needed here).


    (* dummy context to set up H of the correct type, for testing it out *)
    Lemma SomeName (term : Type) (P : term -> term -> Prop) :
      (forall x : term, ~ (exists (y : term), P x y /\ ~ P y x)) ->
      True. (* dummy goal *)
    Proof.
      intro H.
      (* end dummy context *)
    

    (* Here's the long version, with some explanations: *)

      (* this states the goal, result will be put into the context as H' *)
      assert (forall (x y : term), (P x y /\ ~ P y x) -> False) as H'.
        (* get rid of unneeded variables in context, get new args *)
        clear - H; intros x y Pxy.
        (* unfolding the not shows the computational structure of this *)
        unfold not at 1 in H.
        (* yay... (x, y, Pxy) will produce False via H *)
        (* specialize to x and apply... *)
        apply (H x).
        (* ...and provide the witness. *)
        exists y.  exact Pxy.
        (* done. *)
    
      (* let's do it again... *)
      clear H'.
    

    (* you can also do it in a single statement: *)

      assert (forall x y, (P x y /\ ~ P y x) -> False) as H'
        by (clear -H; intros x y Pxy; apply (H x (ex_intro _ y Pxy))).
    
      (* and again... *)
      clear H'.
    

    (* simple stuff like this can also be written by hand: *)

      pose proof (fun x y Pxy => H x (ex_intro _ y Pxy)) as H'; simpl in H'.
    

    (* now you have H' of the right type; optionally get rid of the old H: *)

      clear H; rename H' into H.