{"id":48783056,"url":"https://github.com/matafou/libhyps","last_synced_at":"2026-04-13T15:01:06.903Z","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":"2026-04-07T12:55:03.000Z","size":375,"stargazers_count":23,"open_issues_count":1,"forks_count":3,"subscribers_count":2,"default_branch":"master","last_synced_at":"2026-04-07T14:37:46.453Z","etag":null,"topics":["coq","formal-proofs","hypothesis","proof-assistant","tactical","tactics"],"latest_commit_sha":null,"homepage":"","language":"Rocq Prover","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,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2019-04-04T12:06:03.000Z","updated_at":"2026-02-20T16:28:46.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":20,"template":false,"template_full_name":null,"purl":"pkg:github/Matafou/LibHyps","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","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Matafou%2FLibHyps/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31757482,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-13T13:27:56.013Z","status":"ssl_error","status_checked_at":"2026-04-13T13:21:23.512Z","response_time":93,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":"2026-04-13T15:00:41.819Z","updated_at":"2026-04-13T15:01:06.881Z","avatar_url":"https://github.com/Matafou.png","language":"Rocq Prover","funding_links":[],"categories":[],"sub_categories":[],"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/tests/demo.v) acts as a documentation.\n\n# Short description:\n\nLibHyps provides utilities for hypothesis manipulations. For example a\n    few tacticals to deal with \"new\" hypothesis (new = their name did\n    not appear in the previous goal):\n\n- `tac /r`: applies tac then revert new hypothesis.\n- `tac /s`: applies tac then try to `subst` with new hyps.\n- `tac /n`: applies tac then try to automatically rename new hyps from their type.\n- `tac /g`: applies tac then try to tidy non-prop hyps to save room in your goal.\n- `tac/sng` : combination of the above\n- `tac1 ; { tac2 }` applies tac1, then tac2 on each new hyp (generic version of above).\n- `especialize H at ...` to generate one or several subgoals from the\n  premise(s) of `H` (which can be a hypothesis name or an lemma name).\n  This tactic comes with many variants. See below.\n- `assert premise i of H` generates a subgoal to prove the `i`th\n  premise of `H`, without specializing `H`.\n\n# Quick Test\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/tests/demo.v).\n\n\n\n## The especialize tactic\n\nLet `H` be a hypothesis (or lemma) with type `∀ x y z, H1 x -\u003e H2 y -\u003e H3 x y -\u003e C x y z`.\n\n```\nespecialize H at 2.\n```\n\nCreates a subgoal of the form:\n\n```\n ∀ x y z, H1 x -\u003e H2 y\n```\n  \nand applies it the subgoal to `H` which thus becomes:\n  \n```\nH: ∀ x y z, H1 x -\u003e H3 x y -\u003e C x y z\n```\n\nVariants\n+ `especialize H at 2 as h.` specializes a *copy* of `H` named `h`.\n  Leaves `H` unchanged. quantifying them.\n+ `especialize H at 2,3.`\n+ `especialize H at *.` means specialize *all* premises\n+ `especialize H until 2.` all premises until the 2nd.\n\n+ By default all non-dependent hypothesis of `H` are left quantified\n  (hence its type above `∀ x y z, H1 -\u003e H2`). But you can specify the\n  ones that should rather be transformed into existential variables.\n  Examples:\n\n  + `especialize H at 2 with y.` Creates an evar `?y` subgoal of the form:\n\n    ```\n     ∀ x z, H1 x -\u003e H2 ?y\n    ```\n  \n    and specializes `H` with this subgoal and evar `?y`:\n  \n    ```\n    H: ∀ x z, H1 x -\u003e H3 x ?y -\u003e C x ?y z\n    ```\n    (where H1 and H3 reference `?y` now).\n    \n  + Several evars can be specified, they must be in order:\n\n    ```especialize H at 2 with x,y.```\n\n\nNote that (contrary to previous versions of this library), if you\nforget to list a variable, the tactic won't fail. Instead it will\nsimply leave the variable quantified in the original hypothesis **and\nin subsequently created subgoals**.\n\nFor example, after this:\n\n  ``` coq\n  Lemma test_espec8: forall x:nat, (forall a :nat, a = 1 -\u003e x = 1 -\u003e False) -\u003e x \u003e 1.\n  Proof.\n    intros x h. \n  ```\n\nthe goal looks like this\n\n``` coq\n  x : nat\n  h : forall a : nat, a = 1 -\u003e x = 1 -\u003e False\n  ============================\n  x \u003e 1\n```\n\nthe following tactic:\n\n``` coq\nespecialize h with a at 1.\n```\n\ngives two subgoals:\n\n``` coq\n  x : nat\n  ============================\n  ?a = 1\n\n  x : nat\n  h : x = 1 -\u003e False\n  ============================\n  x \u003e 1\n\n```\n\nWhereas\n\n``` coq\nespecialize h at 1.\n```\n\ngives (note how `a` is quantified in both subgoals, which makes the\nfirst one unprovable):\n\n``` coq\n  x, a : nat\n  ============================\n  a = 1\n  \n  x : nat\n  h : nat -\u003e x = 1 -\u003e False\n  ============================\n  x \u003e 1\n```\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\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 /sng.\n\n  (* Let us instantiate the 2nd premis of h_all_eq_add_add without\n     copying its type. And instantiating u with an evar. *)\n  especialize h_all_eq_add_add_ with u at 2.\n  { apply Nat.add_0_l. }\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.\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 /sng.\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### 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### 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- Hence `onAllHyps autorename` applies `autorename` to all hypothesis.\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 (Ltac2):\n\n```coq\nRequire Import Ltac2.Ltac2.\nFrom Stdlib Require Import List.\nImport ListNotations.\nLocal Set Default Proof Mode \"Classic\". (* Optional This restores ltac1 proof mode. *)\n\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\". *)\nLtac2 rename_hyp_2 _ th :=\n  match! th with\n  | true \u003c\u003e false =\u003e [ String \"tNEQf\" ]\n  | true = false =\u003e [ String \"tEQf\" ]\n  end.\n\nLtac2 Set rename_hyp := rename_hyp_2.\n\n(* Suppose I want to add later another naming rule: *)\nLtac2 rename_hyp_3 n th :=\n  match! th with\n  | Nat.eqb ?x ?y = true =\u003e [ String \"Neqb\"; Rename x ; Rename y ]\n  | true = Nat.eqb ?x ?y =\u003e [ String \"Neqb\" ; Rename x ;  Rename y ]\n  | _ =\u003e rename_hyp_2 n th (* call the previously defined tactic *)\n  end.\n\n(* Then overwrite the definition of rename_hyp using the ::= operator. :*)\nLtac2 Set rename_hyp := rename_hyp_3.\n```\n\nWhere `Rename` stands for calling the naming scheme recursively\n(unless the maximum depth is reached).\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"}