        LibHyps: Small proof maintenance enhancements with Coq

* Dealing with hyps
** ssreflect spirit
*** Operate on hypothesis *before* introducing them.
- Goal's conclusion seen as a stack.
- tactics operate on the top of the stack.
- Post-treatment (administrative) *while* introducing.
- still needs to name hypothesis to revert them.
**** example
#+begin_src coq
x: nat
H: x > 0
===========
forall y:nat, x <= y -> x <> 1 -> x = 2

case. (* = destruct y. *)
by move: H; case: (x) => [| [| s1]].
#+end_src


** Ltac spirit
*** Deal with hypothesis *after* introducing them.
- destruct H, induction H, rewrite ... in H
- rename H into htruc...

   => idea: provide post-treatment tyding tacticals
   => apply them to "recent" hyps
      after an arbitrary tactic.

* Tacticals iterating on (new) hyps
*** New tactical ";{ }"

#+begin_src coq
  tac1 ;{ tac2 }. 
#+end_src
   + applies tac1, then applies tac2 on each new hypothesis from tac1.

example:

#+begin_src coq
   intros ; { fun h => idtac h }
#+end_src
   + *Important*: "new hyp" means "new hyp *name*".

*** Reverse order ";{< }"

#+begin_src coq
  tac1 ;{< tac2 }.
#+end_src

*** Iterating on all hyps instead

#+begin_src coq
  onAllHyps tac.
#+end_src

*** iterate on the *list* of new hyps (for efficiency)

#+begin_src coq
  tac1 ;{! tac2 }. 
  tac1 ;{!< tac2 }. 
#+end_src

tac2 takes a term of type LibHyps.Depl
**** details
#+begin_src coq
Inductive Depl :=
  | DNil: Depl
  | DCons: forall (A:Type) (x:A), Depl -> Depl.

  x : nat
  b1 : bool
  y, b : nat
  ============================
  x < y + b

  Check (DCons nat x (DCons bool b1 DNil)). (* : Depl *)
#+end_src



** DEMO: different use cases
   + revert (short: tac /r)
   + subst (=tac /s=)
   + move non-Prop away to the top (=tac /g=)
   + autorename =(tac /n)=
   + combinations =tac /s/n/g=

* Dealing with big goals (demo)
** A bit help from IDE
*** hide big hyps
*** help read the goal
*** copy hyps names easily
** use case for ";;"
move variables away to focus on intersting (i.e. Prop-sorted) stuff.

* Hypothesis names
** Problem not really interesting
** Been there for decades now
** Known solutions
*** "smack" à la Chlipala
    Maintain adhoc automatic tactics, never perform the proof directly.
    Few adopters?
*** ssrefelct partial solution
    Less use of introduced hyps.
    New hyps never introduced automatically.
    Still need to provide names.
*** others
**** coq-label aka Cortouche
     https://github.com/pedagand/coq-label
     Great idea: never use the name of a hypothesis, use a non
     ambiguous pattern instead:
#+begin_src coq
     Lemma example_patt:
       forall t e1 e2 ,
         is_foo e1 t -> is_foo e2 t -> is_foo e1 t.
     Proof.
       intros.
       exact (\< is_foo e1 _ \>).
     Qed.
#+end_src
   Needs:
   - automatic pattern generation for IDE
   - still a bit hard to read.
   - but promising
   - Maintained?

**** haystac
     https://ptival.github.io/2017/04/10/nameless-tactic-programming-with-haystac/
   - Designate a hyp by an ident appearing in its type
   - Needs more
   - Maintained?

**** LibHyps (present work) Automatic naming from the type of the hyp
***** tactic autorename
  - rename a hypothesis, works with ";;"
#+begin_src coq
  autorename H.
#+end_src

     Simple recursive procedure on the type. PROP SORTED ONLY.
     Pseudo-code (th = type of the hypothesis, n = "depth"):
#+begin_src coq
     Ltac name n th :=
       match n with
       | 0 => fresh "" (*max depth reached, empty name *)
       | S n =>
           rename_hyps n th (* User customized naming *)
           +
           match th with (* default naming *)
           | f t1 t2 t3 => fresh "_f" ^ name n t1 ^ name n t2 ^ name n t3
           | <special cases> => ...
           end
       end.
#+end_src

***** Details
     + prefix "h_", suffix "_" (optional, avoids bad interaction with Coq hacking names)
     + omit implicits (Ltac painful)
     + special cases for equality, negation, option, quantifiers.
     + USER DEFINED NAMING LTAC
     + keep using "rename" and "as" and "intros" for non-Prop hyps

** Demo

* Conclusion
** A distributed Ltac plugin
   opam install coq-libhyps
   
** Need of an ocaml plugin
*** Efficiency problem on big goals
    + Lots of terms building (and typing) to do all this in Ltac.
    + Speed up with a tactical applying to the *list* of new hyps.
      other syntax:
      #+begin_src coq
        tac ; { fun h => ... }. (* equivalent to tac1 ;; tac2. *)
        tac ; {< fun h => ... }. (* tac1 ;!; tac2 *)
        tac ; {! fun lh => ... }. 
        tac ; {!< fun lh => ... }.
      #+end_src
    + But still slow on big goals.
*** implicit detection slow
*** program a new "as" for new hyps - difficult in ltac
*** Nicer customization syntax.
There is already this:
   #+begin_src coq
   Arguments my_relation {A} {R} x y z : rename. 
   #+end_src

Maybe we can add:
#+begin_src coq
   Naming my_relation _ _ x _ z: "_mr" x z.
   Naming my_relation2 _ _ x _ z: "_mr2" x#(n-1) z#n.
#+end_src

or maybe merge both declarations?

*** BUT plugins tend to be less adopted (fear of long term maintenance)
- proofgeneral: coq-libhyps-intros allows to remove dependency: names
  are put in the file. Inconvenient: need to re-insert the names
  during maintenance.
- is this the good philosophy?
** Give it a try.
*** tests, comments and bug reports welcome
https://github.com/Matafou/LibHyps
opam install coq-libhyps

