{"id":13804118,"url":"https://github.com/Matafou/LibHyps","last_synced_at":"2025-05-13T17:31:25.774Z","repository":{"id":85958324,"uuid":"179489645","full_name":"Matafou/LibHyps","owner":"Matafou","description":"A Coq library providing tactics to deal with hypothesis","archived":false,"fork":false,"pushed_at":"2023-12-17T15:05:46.000Z","size":169,"stargazers_count":20,"open_issues_count":0,"forks_count":3,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-08-04T01:03:12.845Z","etag":null,"topics":["coq","formal-proofs","hypothesis","proof-assistant","tactical","tactics"],"latest_commit_sha":null,"homepage":"","language":"Coq","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Matafou.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGES.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-04-04T12:06:03.000Z","updated_at":"2024-08-03T06:05:40.000Z","dependencies_parsed_at":null,"dependency_job_id":"df7005bc-f9c8-4085-be59-cd817fa40791","html_url":"https://github.com/Matafou/LibHyps","commit_stats":null,"previous_names":[],"tags_count":15,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Matafou%2FLibHyps","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Matafou%2FLibHyps/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Matafou%2FLibHyps/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Matafou%2FLibHyps/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Matafou","download_url":"https://codeload.github.com/Matafou/LibHyps/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":225247835,"owners_count":17444122,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["coq","formal-proofs","hypothesis","proof-assistant","tactical","tactics"],"created_at":"2024-08-04T01:00:42.016Z","updated_at":"2025-05-13T17:31:25.765Z","avatar_url":"https://github.com/Matafou.png","language":"Coq","funding_links":[],"categories":["Projects"],"sub_categories":["Libraries"],"readme":"This Library provides several coq tactics and tacticals to deal with\nhypothesis during a proof.\n\nMain page and documentation: https://github.com/Matafou/LibHyps\n\nDemo file [demo.v](https://github.com/Matafou/LibHyps/blob/master/Demo/demo.v) acts as a documentation.\n\n# Short description:\n\nLibHyps provides utilities for hypothesis manipulations. In particular\na new tactic `especialize H` and a set of tacticals to appy or iterate\ntactics either on all hypothesis of a goal or on \"new' hypothesis after\na tactic. It also provide syntax for a few predefined such iterators.\n\n## QUICK REF: especialize\n\nThis tactic was broken in coq v8.18. It is now fixed with some\nmodification: see the remark about evars below\n\n+ `especialize H at 3 [as h].` Creates a subgoal to prove the nth\n    (here the 3rd) dependent premise of `H`, creating necessary evars\n    for non unifiable variables (see below for how to declare this\n    variables). Once proved the subgoal is used to remove the nth\n    premise of `H` (or of a new created hypothesis if the `as` option\n    is given). Se at the bottom of this page for a discussion about\n    the logical completeness of this tactic.\n\n+ `especialize H at * [as h].` Creates one subgoal for each dependent\n    premise of `H`, creating necessary evars for non unifiable\n    variables. Once proved the subgoal is used to remove the premises\n    of `H` (or of a new created hypothesis if the `as` option is\n    given).\n\n+ `especialize H until n [as h].` Creates one subgoal for each n first\n    dependent premises of `H`, creating necessary evars for non\n    unifiable variables. Once proved the subgoal is used to remove the\n    premises of `H` (or of a new created hypothesis if the `as` option\n    is given).\n\n+ all this variant accept (and may *need*) a supplementary argument\n  `with x,y,z` to declare the variables of the hypothesis which must\n  be transformed into existential variables. Examples:\n\n  `especialize H with x,z at n [as h].`,\n  `especialize H with a,b at * [as h].`, etc.\n  \n  These declarations are mandatory (from version 3 of libHyps) due to\n  restriction in coq \u003e= 8.18. If you forget to mention such a variable\n  you will get an error message like this:\n  \n  ```coq\n  Unable to unify \"?n0\" with \"u\" (cannot instantiate \"?n0\"` \u003c!-- --\u003e\n  `because \"u\" is not in its scope: available arguments are \"y\" \"a\" \"b\" \"t\").\n  ```\n\n  I am considering the possibility to have a mode where some of these\n  variables may be declared implicitly.\n\n\n## QUICK REF: Pre-defined tacticals /s /n...\n\nThe most useful user-dedicated tacticals are the following\n\n  + `tac /s` try to apply `subst` on each new hyp.\n  + `tac /r` revert each new hyp.\n  + `tac /n` auto-rename each new hyp.\n  + `tac /g` group all non-Prop new hyp at the top of the goal.\n  + combine the above, as in `tac /s/n/g`.\n  + usual combinations have shortcuts: `\\sng`, `\\sn`,`\\ng`,`\\sg`...\n\n# Install\n\n## Quick install using opam\n\nIf you have not done it already add the coq platform repository to opam!\n\n```bash\nopam repo add coq-released https://coq.inria.fr/opam/released\n```\n\nand then:\n\n```bash\nopam install coq-libhyps\n```\n\n## Quick install using github:\n\nClone the github repository:\n\n```bash\ngit clone https://github.com/Matafou/LibHyps\n```\nthen compile:\n```bash\nconfigure.sh\nmake\nmake install\n```\n\n## Quick test:\n\n```coq\nRequire Import LibHyps.LibHyps.\n```\n\nDemo files [demo.v](https://github.com/Matafou/LibHyps/blob/master/Demo/demo.v).\n\n# More information\n\n## Deprecation from 1.0.x to 2.0.x\n\n  + \"!tac\", \"!!tac\" etc are now only loaded if you do: `Import\n    LibHyps.LegacyNotations.`, the composable tacticals described\n    above are preferred.\n  + \"tac1 ;; tac2\" remains, but you can also use \"tac1; { tac2 }\".\n  + \"tac1 ;!; tac2\" remains, but you can also use \"tac1; {\u003c tac2 }\".\n\n## KNOWN BUGS\n\nDue to Ltac limitation, it is difficult to define a tactic notation\n`tac1 ; { tac2 }` which delays `tac1` and `tac2` in all cases.\nSometimes (rarely) you will have to write `(idtac; tac1); {idtac;\ntac2}`. You may then use tactic notation like: `Tactic Notation tac1'\n:= idtac; tac1.`.\n\n## Examples\n\n```coq\nRequire Import LibHyps.LibHyps.\n\nLemma foo: forall x y z:nat,\n    x = y -\u003e forall  a b t : nat, a+1 = t+2 -\u003e b + 5 = t - 7 -\u003e  (forall u v, v+1 = 1 -\u003e u+1 = 1 -\u003e a+1 = z+2)  -\u003e z = b + x-\u003e True.\nProof.\n  intros.\n  (* ugly names *)\n  Undo.\n  (* Example of using the iterator on new hyps: this prints each new hyp name. *)\n  intros; {fun h =\u003e idtac h}.\n  Undo.\n  (* This gives sensible names to each new hyp. *)\n  intros ; { autorename }.\n  Undo.\n  (* short syntax: *)\n  intros /n.\n  Undo.\n  (* same thing but use subst if possible, and group non prop hyps to the top. *)\n  intros ; { substHyp }; { autorename}; {move_up_types}.\n  Undo.\n  (* short syntax: *)  \n  intros /s/n/g.\n  Undo.\n  (* Even shorter: *)  \n  intros /s/n/g.\n\n  (* Let us instantiate the 2nd premis of h_all_eq_add_add without copying its type: *)\n  especialize h_all_eq_add_add_ with u at 2.\n  { apply Nat.add_0_l. }\n  (* now h_all_eq_add_add is specialized *)\n  Undo 6.\n  intros until 1.\n  (** The taticals apply after any tactic. Notice how H:x=y is not new\n    and hence not substituted, whereas z = b + x is. *)\n  destruct x eqn:heq;intros /sng.\n  - apply I.\n  - apply I.\nQed.\n```\n\n## Short Documentation\n\nThe following explains how it works under the hood, for people willing\nto apply more generic iterators to their own tactics. See also the code.\n  \n### Iterator on all hypothesis\n\n  + `onAllHyps tac` does `tac H` for each hypothesis `H` of the current goal.\n  + `onAllHypsRev tac` same as `onAllHyps tac` but in reverse order\n    (good for reverting for instance).\n\n\n### Iterators on ALL NEW hypothesis (since LibHyps-1.2.0)\n\n  + `tac1 ;{! tac2 }` applies `tac1` to current goal and then `tac2`\n    to *the list* of all new hypothesis in each subgoal (iteration:\n    oldest first).\n    The list is a term of type `LibHyps.TacNewHyps.DList`. See the code.\n  + `tac1 ;{!\u003c tac2 }` is similar but the list of new hyps is reveresed.\n\n### Iterators on EACH NEW hypothesis\n\n  + `tac1 ;{ tac2 }` applies `tac1` to current goal and then `tac2` to\n    each new hypothesis in each subgoal (iteration: older first).\n  + `tac1 ;{\u003c tac2 }` is similar but applies tac2 on newer hyps first.\n\n  + `tac1 ;; tac2` is a synonym of `tac1; { tac2 }`.\n  + `tac1 ;!; tac2` is a synonym of `tac1; {\u003c tac2 }`.\n\n### Customizable hypothesis auto naming system\n\nUsing previous taticals (in particular the `;!;` tactical), some\ntactic allow to rename hypothesis automatically.\n\n- `autorename H` rename `H` according to the current naming scheme\n  (which is customizable, see below).\n\n- `rename_all_hyps` applies `autorename` to all hypothesis.\n\n- `!tac` applies tactic `tac` and then applies autorename to each new\n  hypothesis. Shortcut for: `(Tac ;!; revert_if_norename ;;\n  autorename).`.`\n\n- `!!tac` same as `!tac` with lesser priority (less than `;`) to apply\n  renaming after a group of chained tactics.\n\n#### How to cstomize the naming scheme\n\nThe naming engine analyzes the type of hypothesis and generates a name\nmimicking the first levels of term structure. At each level the\ncustomizable tactic `rename_hyp` is called. One can redefine it at\nwill. It must be of the following form:\n\n```coq\n(** Redefining rename_hyp*)\n(* First define a naming ltac. It takes the current level n and\n   the sub-term th being looked at. It returns a \"name\". *)\nLtac rename_hyp_default n th :=\n   match th with\n   | (ind1 _ _) =\u003e name (`ind1`)\n   | (ind1 _ _ ?x ?y) =\u003e name (`ind1` ++ x#(S n)x ++ y$n)\n   | f1 _ ?x = ?y =\u003e name (`f1` ++ x#n ++ y#n)\n   | _ =\u003e previously_defined_renaming_tac1 n th (* cumulative with previously defined renaming tactics *)\n   | _ =\u003e previously_defined_renaming_tac2 n th\n   end.\n\n(* Then overwrite the definition of rename_hyp using the ::= operator. :*)\nLtac rename_hyp ::= my_rename_hyp.\n```\n\nWhere:\n\n- `` `id` `` to use the name id itself\n- `t$n` to recursively call the naming engine on term t, n being the maximum depth allowed\n- `name ++ name` to concatenate name parts.\n\n\n#### How to define variants of these tacticals?\n\nSome more example of tacticals performing cleaning and renaming on new\nhypothesis.\n\n```coq\n(* subst or revert *)\nTactic Notation (at level 4) \"??\" tactic4(tac1) :=\n  (tac1 ;; substHyp ;!; revertHyp).\n(* subst or rename or revert *)\nTactic Notation \"!!!\" tactic3(Tac) := (Tac ;; substHyp ;!; revert_if_norename ;; autorename).\n(* subst or rename or revert + move up if in (Set or Type). *)\nTactic Notation (at level 4) \"!!!!\" tactic4(Tac) :=\n      (Tac ;; substHyp ;!; revert_if_norename ;; autorename ;; move_up_types).\n```\n\n\n# About the logical \"completeness\" of `especialize`\n\nSuppose we have this goal:\n\n\n```coq\n  Lemma foo: (forall x:nat, x = 1 -\u003e (x\u003e0) -\u003e x \u003c 0) -\u003e False.\n  Proof.\n    intros h.\n\nh : forall x : nat, x = 1 -\u003e x \u003e 0 -\u003e x \u003c 0\n  ============================\n  False\n\nespecialize h with x at 2.\n\n\n  h : ?x = 1 -\u003e ?x \u003e 0 -\u003e ?x \u003c 0\n  ============================\n  ?x \u003e 0\n\ngoal 2 (ID 88) is:\n False\n\n```\n\nNote that in this case it would be preferable (and logically more\naccurate) to have a hypothesis `h2: ?x = 1` in the context, since the\npremise 2 of H needs only to be proved when premise 1 is true. Note\nhowever that in this kind of situation most users would wait to be\nable to prove premise 1 before instantiating premise 2. `especialize`\ndoes not cover this kind of subtleties. Another tactic is under\ndevelopment to support this kind of reasoning.\n\n\n\n\u003c!--  LocalWords:  subgoal unifiable evars\n --\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FMatafou%2FLibHyps","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FMatafou%2FLibHyps","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FMatafou%2FLibHyps/lists"}