{"id":50589609,"url":"https://github.com/tristan-f-r/mathlib4-tactics","last_synced_at":"2026-06-05T09:03:58.430Z","repository":{"id":271491573,"uuid":"913631812","full_name":"tristan-f-r/mathlib4-tactics","owner":"tristan-f-r","description":"autogenerated tactics list for mathlib4","archived":false,"fork":false,"pushed_at":"2025-01-09T04:06:09.000Z","size":94,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-26T10:36:51.637Z","etag":null,"topics":["lean4","mathlib4"],"latest_commit_sha":null,"homepage":"","language":"Lean","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tristan-f-r.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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":"2025-01-08T04:05:41.000Z","updated_at":"2025-01-09T04:06:12.000Z","dependencies_parsed_at":"2025-01-08T05:18:40.047Z","dependency_job_id":"31a4a92f-d8bb-4fdc-b994-96036b9e896c","html_url":"https://github.com/tristan-f-r/mathlib4-tactics","commit_stats":null,"previous_names":["leodog896/mathlib4-tactics","tristan-f-r/mathlib4-tactics"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/tristan-f-r/mathlib4-tactics","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tristan-f-r%2Fmathlib4-tactics","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tristan-f-r%2Fmathlib4-tactics/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tristan-f-r%2Fmathlib4-tactics/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tristan-f-r%2Fmathlib4-tactics/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tristan-f-r","download_url":"https://codeload.github.com/tristan-f-r/mathlib4-tactics/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tristan-f-r%2Fmathlib4-tactics/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33937718,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-05T02:00:06.157Z","response_time":120,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":["lean4","mathlib4"],"created_at":"2026-06-05T09:03:56.549Z","updated_at":"2026-06-05T09:03:58.418Z","avatar_url":"https://github.com/tristan-f-r.png","language":"Lean","funding_links":[],"categories":[],"sub_categories":[],"readme":"# mathlib4-tactics\n\nAn autogenerated list of tactics from a modified `#help tactic`.\n\n\n# \"#adaptation_note\" [«tactic#adaptation_note_»](https://leanprover-community.github.io/mathlib4_docs/search.html?q=«tactic#adaptation_note_»)\n\nAdaptation notes are comments that are used to indicate that a piece of code\nhas been changed to accommodate a change in Lean core.\nThey typically require further action/maintenance to be taken in the future.\n\n# \"#check\" [Mathlib.Tactic.«tactic#check__»](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Mathlib.Tactic.«tactic#check__»)\n\nThe `#check t` tactic elaborates the term `t` and then pretty prints it with its type as `e : ty`.\n\nIf `t` is an identifier, then it pretty prints a type declaration form\nfor the global constant `t` instead.\nUse `#check (t)` to pretty print it as an elaborated expression.\n\nLike the `#check` command, the `#check` tactic allows stuck typeclass instance problems.\nThese become metavariables in the output.\n\n# \"#find\" [Mathlib.Tactic.Find.«tactic#find_»](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Mathlib.Tactic.Find.«tactic#find_»)\n\n\n# \"#leansearch\" [LeanSearchClient.leansearch_search_tactic](https://leanprover-community.github.io/mathlib4_docs/search.html?q=LeanSearchClient.leansearch_search_tactic)\n\nSearch [LeanSearch](https://leansearch.net/) from within Lean.\nQueries should be a string that ends with a `.` or `?`. This works as a command, as a term\nand as a tactic as in the following examples. In tactic mode, only valid tactics are displayed.\n\n```lean\n#leansearch \"If a natural number n is less than m, then the successor of n is less than the successor of m.\"\n\nexample := #leansearch \"If a natural number n is less than m, then the successor of n is less than the successor of m.\"\n\nexample : 3 ≤ 5 := by\n  #leansearch \"If a natural number n is less than m, then the successor of n is less than the successor of m.\"\n  sorry\n```\n\n# \"#loogle\" [LeanSearchClient.loogle_tactic](https://leanprover-community.github.io/mathlib4_docs/search.html?q=LeanSearchClient.loogle_tactic)\n\nSearch [Loogle](https://loogle.lean-lang.org/json) from within Lean. This can be used as a command, term or tactic as in the following examples. In the case of a tactic, only valid tactics are displayed.\n\n\n```lean\n#loogle List ?a → ?a\n\nexample := #loogle List ?a → ?a\n\nexample : 3 ≤ 5 := by\n  #loogle Nat.succ_le_succ\n  sorry\n\n```\n\n## Loogle Usage\n\nLoogle finds definitions and lemmas in various ways:\n\nBy constant:\n🔍 Real.sin\nfinds all lemmas whose statement somehow mentions the sine function.\n\nBy lemma name substring:\n🔍 \\\"differ\\\"\nfinds all lemmas that have \\\"differ\\\" somewhere in their lemma name.\n\nBy subexpression:\n🔍 _ * (_ ^ _)\nfinds all lemmas whose statements somewhere include a product where the second argument is raised to some power.\n\nThe pattern can also be non-linear, as in\n🔍 Real.sqrt ?a * Real.sqrt ?a\n\nIf the pattern has parameters, they are matched in any order. Both of these will find List.map:\n🔍 (?a -\u003e ?b) -\u003e List ?a -\u003e List ?b\n🔍 List ?a -\u003e (?a -\u003e ?b) -\u003e List ?b\n\nBy main conclusion:\n🔍 |- tsum _ = _ * tsum _\nfinds all lemmas where the conclusion (the subexpression to the right of all → and ∀) has the given shape.\n\nAs before, if the pattern has parameters, they are matched against the hypotheses of the lemma in any order; for example,\n🔍 |- _ \u003c _ → tsum _ \u003c tsum _\nwill find tsum_lt_tsum even though the hypothesis f i \u003c g i is not the last.\n\nIf you pass more than one such search filter, separated by commas Loogle will return lemmas which match all of them. The search\n🔍 Real.sin, \\\"two\\\", tsum, _ * _, _ ^ _, |- _ \u003c _ → _\nwoould find all lemmas which mention the constants Real.sin and tsum, have \\\"two\\\" as a substring of the lemma name, include a product and a power somewhere in the type, and have a hypothesis of the form _ \u003c _ (if there were any such lemmas). Metavariables (?a) are assigned independently in each filter.\n\n# \"#loogle\" [LeanSearchClient.just_loogle_tactic](https://leanprover-community.github.io/mathlib4_docs/search.html?q=LeanSearchClient.just_loogle_tactic)\n\n\n# \"#moogle\" [LeanSearchClient.moogle_search_tactic](https://leanprover-community.github.io/mathlib4_docs/search.html?q=LeanSearchClient.moogle_search_tactic)\n\nSearch [Moogle](https://www.moogle.ai/api/search) from within Lean.\nQueries should be a string that ends with a `.` or `?`. This works as a command, as a term\nand as a tactic as in the following examples. In tactic mode, only valid tactics are displayed.\n\n```lean\n#moogle \"If a natural number n is less than m, then the successor of n is less than the successor of m.\"\n\nexample := #moogle \"If a natural number n is less than m, then the successor of n is less than the successor of m.\"\n\nexample : 3 ≤ 5 := by\n  #moogle \"If a natural number n is less than m, then the successor of n is less than the successor of m.\"\n  sorry\n```\n\n# \"(\" [Parser.Tactic.paren](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Parser.Tactic.paren)\n\n`(tacs)` executes a list of tactics in sequence, without requiring that\nthe goal be closed at the end like `· tacs`. Like `by` itself, the tactics\ncan be either separated by newlines or `;`.\n\n# \"\u003c;\u003e\" [Batteries.Tactic.seq_focus](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Batteries.Tactic.seq_focus)\n\n`t \u003c;\u003e [t1; t2; ...; tn]` focuses on the first goal and applies `t`, which should result in `n`\nsubgoals. It then applies each `ti` to the corresponding goal and collects the resulting\nsubgoals.\n\n# \"\u003c;\u003e\" [Parser.Tactic.«tactic_\u003c;\u003e_»](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Parser.Tactic.«tactic_\u003c;\u003e_»)\n\n`tac \u003c;\u003e tac'` runs `tac` on the main goal and `tac'` on each produced goal,\nconcatenating all goals produced by `tac'`.\n\n# \"_\" [Batteries.Tactic.tactic_](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Batteries.Tactic.tactic_)\n\n`_` in tactic position acts like the `done` tactic: it fails and gives the list\nof goals if there are any. It is useful as a placeholder after starting a tactic block\nsuch as `by _` to make it syntactically correct and show the current goal.\n\n# \"abel\" [Mathlib.Tactic.Abel.abel_term](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Mathlib.Tactic.Abel.abel_term)\n\nUnsupported legacy syntax from mathlib3, which allowed passing additional terms to `abel`.\n\n# \"abel\" [Mathlib.Tactic.Abel.abel](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Mathlib.Tactic.Abel.abel)\n\nTactic for evaluating expressions in abelian groups.\n\n* `abel!` will use a more aggressive reducibility setting to determine equality of atoms.\n* `abel1` fails if the target is not an equality.\n\nFor example:\n```\nexample [AddCommMonoid α] (a b : α) : a + (b + a) = a + a + b := by abel\nexample [AddCommGroup α] (a : α) : (3 : ℤ) • a = a + (2 : ℤ) • a := by abel\n```\n\n# \"abel!\" [Mathlib.Tactic.Abel.abel!_term](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Mathlib.Tactic.Abel.abel!_term)\n\nUnsupported legacy syntax from mathlib3, which allowed passing additional terms to `abel!`.\n\n# \"abel!\" [Mathlib.Tactic.Abel.tacticAbel!](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Mathlib.Tactic.Abel.tacticAbel!)\n\nTactic for evaluating expressions in abelian groups.\n\n* `abel!` will use a more aggressive reducibility setting to determine equality of atoms.\n* `abel1` fails if the target is not an equality.\n\nFor example:\n```\nexample [AddCommMonoid α] (a b : α) : a + (b + a) = a + a + b := by abel\nexample [AddCommGroup α] (a : α) : (3 : ℤ) • a = a + (2 : ℤ) • a := by abel\n```\n\n# \"abel1\" [Mathlib.Tactic.Abel.abel1](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Mathlib.Tactic.Abel.abel1)\n\nTactic for solving equations in the language of\n*additive*, commutative monoids and groups.\nThis version of `abel` fails if the target is not an equality\nthat is provable by the axioms of commutative monoids/groups.\n\n`abel1!` will use a more aggressive reducibility setting to identify atoms.\nThis can prove goals that `abel` cannot, but is more expensive.\n\n# \"abel1!\" [Mathlib.Tactic.Abel.abel1!](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Mathlib.Tactic.Abel.abel1!)\n\nTactic for solving equations in the language of\n*additive*, commutative monoids and groups.\nThis version of `abel` fails if the target is not an equality\nthat is provable by the axioms of commutative monoids/groups.\n\n`abel1!` will use a more aggressive reducibility setting to identify atoms.\nThis can prove goals that `abel` cannot, but is more expensive.\n\n# \"abel_nf\" [Mathlib.Tactic.Abel.abelNF](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Mathlib.Tactic.Abel.abelNF)\n\nSimplification tactic for expressions in the language of abelian groups,\nwhich rewrites all group expressions into a normal form.\n* `abel_nf!` will use a more aggressive reducibility setting to identify atoms.\n* `abel_nf (config := cfg)` allows for additional configuration:\n  * `red`: the reducibility setting (overridden by `!`)\n  * `recursive`: if true, `abel_nf` will also recurse into atoms\n* `abel_nf` works as both a tactic and a conv tactic.\n  In tactic mode, `abel_nf at h` can be used to rewrite in a hypothesis.\n\n# \"abel_nf!\" [Mathlib.Tactic.Abel.tacticAbel_nf!__](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Mathlib.Tactic.Abel.tacticAbel_nf!__)\n\nSimplification tactic for expressions in the language of abelian groups,\nwhich rewrites all group expressions into a normal form.\n* `abel_nf!` will use a more aggressive reducibility setting to identify atoms.\n* `abel_nf (config := cfg)` allows for additional configuration:\n  * `red`: the reducibility setting (overridden by `!`)\n  * `recursive`: if true, `abel_nf` will also recurse into atoms\n* `abel_nf` works as both a tactic and a conv tactic.\n  In tactic mode, `abel_nf at h` can be used to rewrite in a hypothesis.\n\n# \"absurd\" [Batteries.Tactic.tacticAbsurd_](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Batteries.Tactic.tacticAbsurd_)\n\nGiven a proof `h` of `p`, `absurd h` changes the goal to `⊢ ¬ p`.\nIf `p` is a negation `¬q` then the goal is changed to `⊢ q` instead.\n\n# \"ac_change\" [Mathlib.Tactic.acChange](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Mathlib.Tactic.acChange)\n\n`ac_change g using n` is `convert_to g using n` followed by `ac_rfl`. It is useful for\nrearranging/reassociating e.g. sums:\n```lean\nexample (a b c d e f g N : ℕ) : (a + b) + (c + d) + (e + f) + g ≤ N := by\n  ac_change a + d + e + f + c + g + b ≤ _\n  -- ⊢ a + d + e + f + c + g + b ≤ N\n```\n\n# \"ac_nf\" [Parser.Tactic.tacticAc_nf_](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Parser.Tactic.tacticAc_nf_)\n\n`ac_nf` normalizes equalities up to application of an associative and commutative operator.\n- `ac_nf` normalizes all hypotheses and the goal target of the goal.\n- `ac_nf at l` normalizes at location(s) `l`, where `l` is either `*` or a\n  list of hypotheses in the local context. In the latter case, a turnstile `⊢` or `|-`\n  can also be used, to signify the target of the goal.\n```\ninstance : Associative (α := Nat) (.+.) := ⟨Nat.add_assoc⟩\ninstance : Commutative (α := Nat) (.+.) := ⟨Nat.add_comm⟩\n\nexample (a b c d : Nat) : a + b + c + d = d + (b + c) + a := by\n ac_nf\n -- goal: a + (b + (c + d)) = a + (b + (c + d))\n```\n\n# \"ac_nf0\" [Parser.Tactic.acNf0](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Parser.Tactic.acNf0)\n\nImplementation of `ac_nf` (the full `ac_nf` calls `trivial` afterwards).\n\n# \"ac_rfl\" [Parser.Tactic.acRfl](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Parser.Tactic.acRfl)\n\n`ac_rfl` proves equalities up to application of an associative and commutative operator.\n```\ninstance : Associative (α := Nat) (.+.) := ⟨Nat.add_assoc⟩\ninstance : Commutative (α := Nat) (.+.) := ⟨Nat.add_comm⟩\n\nexample (a b c d : Nat) : a + b + c + d = d + (b + c) + a := by ac_rfl\n```\n\n# \"admit\" [Parser.Tactic.tacticAdmit](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Parser.Tactic.tacticAdmit)\n\n`admit` is a synonym for `sorry`.\n\n# \"aesop\" [Aesop.Frontend.Parser.aesopTactic](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Aesop.Frontend.Parser.aesopTactic)\n\n`aesop \u003cclause\u003e*` tries to solve the current goal by applying a set of rules\nregistered with the `@[aesop]` attribute. See [its\nREADME](https://github.com/JLimperg/aesop#readme) for a tutorial and a\nreference.\n\nThe variant `aesop?` prints the proof it found as a `Try this` suggestion.\n\nClauses can be used to customise the behaviour of an Aesop call. Available\nclauses are:\n\n- `(add \u003cphase\u003e \u003cpriority\u003e \u003cbuilder\u003e \u003crule\u003e)` adds a rule. `\u003cphase\u003e` is\n  `unsafe`, `safe` or `norm`. `\u003cpriority\u003e` is a percentage for unsafe rules and\n  an integer for safe and norm rules. `\u003crule\u003e` is the name of a declaration or\n  local hypothesis. `\u003cbuilder\u003e` is the rule builder used to turn `\u003crule\u003e` into\n  an Aesop rule. Example: `(add unsafe 50% apply Or.inl)`.\n- `(erase \u003crule\u003e)` disables a globally registered Aesop rule. Example: `(erase\n  Aesop.BuiltinRules.assumption)`.\n- `(rule_sets := [\u003cruleset\u003e,*])` enables or disables named sets of rules for\n  this Aesop call. Example: `(rule_sets := [-builtin, MyRuleSet])`.\n- `(config { \u003copt\u003e := \u003cvalue\u003e })` adjusts Aesop's search options. See\n  `Aesop.Options`.\n- `(simp_config { \u003copt\u003e := \u003cvalue\u003e })` adjusts options for Aesop's built-in\n  `simp` rule. The given options are directly passed to `simp`. For example,\n  `(simp_config := { zeta := false })` makes Aesop use\n  `simp (config := { zeta := false })`.\n\n# \"aesop?\" [Aesop.Frontend.Parser.aesopTactic?](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Aesop.Frontend.Parser.aesopTactic?)\n\n`aesop \u003cclause\u003e*` tries to solve the current goal by applying a set of rules\nregistered with the `@[aesop]` attribute. See [its\nREADME](https://github.com/JLimperg/aesop#readme) for a tutorial and a\nreference.\n\nThe variant `aesop?` prints the proof it found as a `Try this` suggestion.\n\nClauses can be used to customise the behaviour of an Aesop call. Available\nclauses are:\n\n- `(add \u003cphase\u003e \u003cpriority\u003e \u003cbuilder\u003e \u003crule\u003e)` adds a rule. `\u003cphase\u003e` is\n  `unsafe`, `safe` or `norm`. `\u003cpriority\u003e` is a percentage for unsafe rules and\n  an integer for safe and norm rules. `\u003crule\u003e` is the name of a declaration or\n  local hypothesis. `\u003cbuilder\u003e` is the rule builder used to turn `\u003crule\u003e` into\n  an Aesop rule. Example: `(add unsafe 50% apply Or.inl)`.\n- `(erase \u003crule\u003e)` disables a globally registered Aesop rule. Example: `(erase\n  Aesop.BuiltinRules.assumption)`.\n- `(rule_sets := [\u003cruleset\u003e,*])` enables or disables named sets of rules for\n  this Aesop call. Example: `(rule_sets := [-builtin, MyRuleSet])`.\n- `(config { \u003copt\u003e := \u003cvalue\u003e })` adjusts Aesop's search options. See\n  `Aesop.Options`.\n- `(simp_config { \u003copt\u003e := \u003cvalue\u003e })` adjusts options for Aesop's built-in\n  `simp` rule. The given options are directly passed to `simp`. For example,\n  `(simp_config := { zeta := false })` makes Aesop use\n  `simp (config := { zeta := false })`.\n\n# \"aesop_cat\" [CategoryTheory.aesop_cat](https://leanprover-community.github.io/mathlib4_docs/search.html?q=CategoryTheory.aesop_cat)\n\nA thin wrapper for `aesop` which adds the `CategoryTheory` rule set and\nallows `aesop` to look through semireducible definitions when calling `intros`.\nThis tactic fails when it is unable to solve the goal, making it suitable for\nuse in auto-params.\n\n# \"aesop_cat?\" [CategoryTheory.aesop_cat?](https://leanprover-community.github.io/mathlib4_docs/search.html?q=CategoryTheory.aesop_cat?)\n\nWe also use `aesop_cat?` to pass along a `Try this` suggestion when using `aesop_cat`\n\n# \"aesop_cat_nonterminal\" [CategoryTheory.aesop_cat_nonterminal](https://leanprover-community.github.io/mathlib4_docs/search.html?q=CategoryTheory.aesop_cat_nonterminal)\n\nA variant of `aesop_cat` which does not fail when it is unable to solve the\ngoal. Use this only for exploration! Nonterminal `aesop` is even worse than\nnonterminal `simp`.\n\n# \"aesop_unfold\" [Aesop.tacticAesop_unfold_](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Aesop.tacticAesop_unfold_)\n\n\n# \"aesop_unfold\" [Aesop.tacticAesop_unfold_At_](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Aesop.tacticAesop_unfold_At_)\n\n\n# \"algebraize\" [Mathlib.Tactic.tacticAlgebraize__](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Mathlib.Tactic.tacticAlgebraize__)\n\nTactic that, given `RingHom`s, adds the corresponding `Algebra` and (if possible)\n`IsScalarTower` instances, as well as `Algebra` corresponding to `RingHom` properties available\nas hypotheses.\n\nExample: given `f : A →+* B` and `g : B →+* C`, and `hf : f.FiniteType`, `algebraize [f, g]` will\nadd the instances `Algebra A B`, `Algebra B C`, and `Algebra.FiniteType A B`.\n\nSee the `algebraize` tag for instructions on what properties can be added.\n\nThe tactic also comes with a configuration option `properties`. If set to `true` (default), the\ntactic searches through the local context for `RingHom` properties that can be converted to\n`Algebra` properties. The macro `algebraize_only` calls\n`algebraize (config := {properties := false})`,\nso in other words it only adds `Algebra` and `IsScalarTower` instances.\n\n# \"algebraize_only\" [Mathlib.Tactic.tacticAlgebraize_only__](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Mathlib.Tactic.tacticAlgebraize_only__)\n\nVersion of `algebraize`, which only adds `Algebra` instances and `IsScalarTower` instances,\nbut does not try to add any instances about any properties tagged with\n`@[algebraize]`, like for example `Finite` or `IsIntegral`.\n\n# \"all_goals\" [Parser.Tactic.allGoals](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Parser.Tactic.allGoals)\n\n`all_goals tac` runs `tac` on each goal, concatenating the resulting goals.\nIf the tactic fails on any goal, the entire `all_goals` tactic fails.\n\nSee also `any_goals tac`.\n\n# \"and_intros\" [Parser.Tactic.tacticAnd_intros](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Parser.Tactic.tacticAnd_intros)\n\n`and_intros` applies `And.intro` until it does not make progress.\n\n# \"any_goals\" [Parser.Tactic.anyGoals](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Parser.Tactic.anyGoals)\n\n`any_goals tac` applies the tactic `tac` to every goal,\nconcating the resulting goals for successful tactic applications.\nIf the tactic fails on all of the goals, the entire `any_goals` tactic fails.\n\nThis tactic is like `all_goals try tac` except that it fails if none of the applications of `tac` succeeds.\n\n# \"apply\" [Mathlib.Tactic.tacticApply_At_](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Mathlib.Tactic.tacticApply_At_)\n\n`apply t at i` will use forward reasoning with `t` at the hypothesis `i`.\nExplicitly, if `t : α₁ → ⋯ → αᵢ → ⋯ → αₙ` and `i` has type `αᵢ`, then this tactic will add\nmetavariables/goals for any terms of `αⱼ` for `j = 1, …, i-1`,\nthen replace the type of `i` with `αᵢ₊₁ → ⋯ → αₙ` by applying those metavariables and the\noriginal `i`.\n\n# \"apply\" [Parser.Tactic.apply](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Parser.Tactic.apply)\n\n`apply e` tries to match the current goal against the conclusion of `e`'s type.\nIf it succeeds, then the tactic returns as many subgoals as the number of premises that\nhave not been fixed by type inference or type class resolution.\nNon-dependent premises are added before dependent ones.\n\nThe `apply` tactic uses higher-order pattern matching, type class resolution,\nand first-order unification with dependent types.\n\n# \"apply\" [Mathlib.Tactic.applyWith](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Mathlib.Tactic.applyWith)\n\n`apply (config := cfg) e` is like `apply e` but allows you to provide a configuration\n`cfg : ApplyConfig` to pass to the underlying `apply` operation.\n\n# \"apply?\" [Parser.Tactic.apply?](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Parser.Tactic.apply?)\n\nSearches environment for definitions or theorems that can refine the goal using `apply`\nwith conditions resolved when possible with `solve_by_elim`.\n\nThe optional `using` clause provides identifiers in the local context that must be\nused when closing the goal.\n\n# \"apply_assumption\" [Parser.Tactic.applyAssumption](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Parser.Tactic.applyAssumption)\n\n`apply_assumption` looks for an assumption of the form `... → ∀ _, ... → head`\nwhere `head` matches the current goal.\n\nYou can specify additional rules to apply using `apply_assumption [...]`.\nBy default `apply_assumption` will also try `rfl`, `trivial`, `congrFun`, and `congrArg`.\nIf you don't want these, or don't want to use all hypotheses, use `apply_assumption only [...]`.\nYou can use `apply_assumption [-h]` to omit a local hypothesis.\nYou can use `apply_assumption using [a₁, ...]` to use all lemmas which have been labelled\nwith the attributes `aᵢ` (these attributes must be created using `register_label_attr`).\n\n`apply_assumption` will use consequences of local hypotheses obtained via `symm`.\n\nIf `apply_assumption` fails, it will call `exfalso` and try again.\nThus if there is an assumption of the form `P → ¬ Q`, the new tactic state\nwill have two goals, `P` and `Q`.\n\nYou can pass a further configuration via the syntax `apply_rules (config := {...}) lemmas`.\nThe options supported are the same as for `solve_by_elim` (and include all the options for `apply`).\n\n# \"apply_ext_theorem\" [Ext.applyExtTheorem](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Ext.applyExtTheorem)\n\nApply a single extensionality theorem to the current goal.\n\n# \"apply_fun\" [Mathlib.Tactic.applyFun](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Mathlib.Tactic.applyFun)\n\nApply a function to an equality or inequality in either a local hypothesis or the goal.\n\n* If we have `h : a = b`, then `apply_fun f at h` will replace this with `h : f a = f b`.\n* If we have `h : a ≤ b`, then `apply_fun f at h` will replace this with `h : f a ≤ f b`,\n  and create a subsidiary goal `Monotone f`.\n  `apply_fun` will automatically attempt to discharge this subsidiary goal using `mono`,\n  or an explicit solution can be provided with `apply_fun f at h using P`, where `P : Monotone f`.\n* If we have `h : a \u003c b`, then `apply_fun f at h` will replace this with `h : f a \u003c f b`,\n  and create a subsidiary goal `StrictMono f` and behaves as in the previous case.\n* If we have `h : a ≠ b`, then `apply_fun f at h` will replace this with `h : f a ≠ f b`,\n  and create a subsidiary goal `Injective f` and behaves as in the previous two cases.\n* If the goal is `a ≠ b`, `apply_fun f` will replace this with `f a ≠ f b`.\n* If the goal is `a = b`, `apply_fun f` will replace this with `f a = f b`,\n  and create a subsidiary goal `injective f`.\n  `apply_fun` will automatically attempt to discharge this subsidiary goal using local hypotheses,\n  or if `f` is actually an `Equiv`,\n  or an explicit solution can be provided with `apply_fun f using P`, where `P : Injective f`.\n* If the goal is `a ≤ b` (or similarly for `a \u003c b`), and `f` is actually an `OrderIso`,\n  `apply_fun f` will replace the goal with `f a ≤ f b`.\n  If `f` is anything else (e.g. just a function, or an `Equiv`), `apply_fun` will fail.\n\n\nTypical usage is:\n```lean\nopen Function\n\nexample (X Y Z : Type) (f : X → Y) (g : Y → Z) (H : Injective \u003c| g ∘ f) :\n    Injective f := by\n  intros x x' h\n  apply_fun g at h\n  exact H h\n```\n\nThe function `f` is handled similarly to how it would be handled by `refine` in that `f` can contain\nplaceholders. Named placeholders (like `?a` or `?_`) will produce new goals.\n\n# \"apply_mod_cast\" [Parser.Tactic.tacticApply_mod_cast_](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Parser.Tactic.tacticApply_mod_cast_)\n\nNormalize casts in the goal and the given expression, then `apply` the expression to the goal.\n\n# \"apply_rfl\" [Parser.Tactic.applyRfl](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Parser.Tactic.applyRfl)\n\nThe same as `rfl`, but without trying `eq_refl` at the end.\n\n# \"apply_rules\" [Parser.Tactic.applyRules](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Parser.Tactic.applyRules)\n\n`apply_rules [l₁, l₂, ...]` tries to solve the main goal by iteratively\napplying the list of lemmas `[l₁, l₂, ...]` or by applying a local hypothesis.\nIf `apply` generates new goals, `apply_rules` iteratively tries to solve those goals.\nYou can use `apply_rules [-h]` to omit a local hypothesis.\n\n`apply_rules` will also use `rfl`, `trivial`, `congrFun` and `congrArg`.\nThese can be disabled, as can local hypotheses, by using `apply_rules only [...]`.\n\nYou can use `apply_rules using [a₁, ...]` to use all lemmas which have been labelled\nwith the attributes `aᵢ` (these attributes must be created using `register_label_attr`).\n\nYou can pass a further configuration via the syntax `apply_rules (config := {...})`.\nThe options supported are the same as for `solve_by_elim` (and include all the options for `apply`).\n\n`apply_rules` will try calling `symm` on hypotheses and `exfalso` on the goal as needed.\nThis can be disabled with `apply_rules (config := {symm := false, exfalso := false})`.\n\nYou can bound the iteration depth using the syntax `apply_rules (config := {maxDepth := n})`.\n\nUnlike `solve_by_elim`, `apply_rules` does not perform backtracking, and greedily applies\na lemma from the list until it gets stuck.\n\n# \"arith_mult\" [ArithmeticFunction.arith_mult](https://leanprover-community.github.io/mathlib4_docs/search.html?q=ArithmeticFunction.arith_mult)\n\n`arith_mult` solves goals of the form `IsMultiplicative f` for `f : ArithmeticFunction R`\nby applying lemmas tagged with the user attribute `arith_mult`.\n\n# \"arith_mult?\" [ArithmeticFunction.arith_mult?](https://leanprover-community.github.io/mathlib4_docs/search.html?q=ArithmeticFunction.arith_mult?)\n\n`arith_mult` solves goals of the form `IsMultiplicative f` for `f : ArithmeticFunction R`\nby applying lemmas tagged with the user attribute `arith_mult`, and prints out the generated\nproof term.\n\n# \"array_get_dec\" [Array.tacticArray_get_dec](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Array.tacticArray_get_dec)\n\nThis tactic, added to the `decreasing_trivial` toolbox, proves that\n`sizeOf arr[i] \u003c sizeOf arr`, which is useful for well founded recursions\nover a nested inductive like `inductive T | mk : Array T → T`.\n\n# \"array_mem_dec\" [Array.tacticArray_mem_dec](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Array.tacticArray_mem_dec)\n\nThis tactic, added to the `decreasing_trivial` toolbox, proves that `sizeOf a \u003c sizeOf arr`\nprovided that `a ∈ arr` which is useful for well founded recursions over a nested inductive like\n`inductive T | mk : Array T → T`.\n\n# \"assumption\" [Parser.Tactic.assumption](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Parser.Tactic.assumption)\n\n`assumption` tries to solve the main goal using a hypothesis of compatible type, or else fails.\nNote also the `‹t›` term notation, which is a shorthand for `show t by assumption`.\n\n# \"assumption'\" [Mathlib.Tactic.tacticAssumption'](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Mathlib.Tactic.tacticAssumption')\n\nTry calling `assumption` on all goals; succeeds if it closes at least one goal.\n\n# \"assumption_mod_cast\" [Parser.Tactic.tacticAssumption_mod_cast_](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Parser.Tactic.tacticAssumption_mod_cast_)\n\n`assumption_mod_cast` is a variant of `assumption` that solves the goal\nusing a hypothesis. Unlike `assumption`, it first pre-processes the goal and\neach hypothesis to move casts as far outwards as possible, so it can be used\nin more situations.\n\nConcretely, it runs `norm_cast` on the goal. For each local hypothesis `h`, it also\nnormalizes `h` with `norm_cast` and tries to use that to close the goal.\n\n# \"aux_group₁\" [Mathlib.Tactic.Group.aux_group₁](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Mathlib.Tactic.Group.aux_group₁)\n\nAuxiliary tactic for the `group` tactic. Calls the simplifier only.\n\n# \"aux_group₂\" [Mathlib.Tactic.Group.aux_group₂](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Mathlib.Tactic.Group.aux_group₂)\n\nAuxiliary tactic for the `group` tactic. Calls `ring_nf` to normalize exponents.\n\n# \"bddDefault\" [tacticBddDefault](https://leanprover-community.github.io/mathlib4_docs/search.html?q=tacticBddDefault)\n\nSets are automatically bounded or cobounded in complete lattices. To use the same statements\nin complete and conditionally complete lattices but let automation fill automatically the\nboundedness proofs in complete lattices, we use the tactic `bddDefault` in the statements,\nin the form `(hA : BddAbove A := by bddDefault)`.\n\n# \"beta_reduce\" [Mathlib.Tactic.betaReduceStx](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Mathlib.Tactic.betaReduceStx)\n\n`beta_reduce at loc` completely beta reduces the given location.\nThis also exists as a `conv`-mode tactic.\n\nThis means that whenever there is an applied lambda expression such as\n`(fun x =\u003e f x) y` then the argument is substituted into the lambda expression\nyielding an expression such as `f y`.\n\n# \"bicategory\" [Mathlib.Tactic.Bicategory.tacticBicategory](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Mathlib.Tactic.Bicategory.tacticBicategory)\n\nUse the coherence theorem for bicategories to solve equations in a bicategory,\nwhere the two sides only differ by replacing strings of bicategory structural morphisms\n(that is, associators, unitors, and identities)\nwith different strings of structural morphisms with the same source and target.\n\nThat is, `bicategory` can handle goals of the form\n`a ≫ f ≫ b ≫ g ≫ c = a' ≫ f ≫ b' ≫ g ≫ c'`\nwhere `a = a'`, `b = b'`, and `c = c'` can be proved using `bicategory_coherence`.\n\n# \"bicategory_coherence\" [Mathlib.Tactic.BicategoryCoherence.tacticBicategory_coherence](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Mathlib.Tactic.BicategoryCoherence.tacticBicategory_coherence)\n\nCoherence tactic for bicategories.\nUse `pure_coherence` instead, which is a frontend to this one.\n\n# \"bicategory_coherence\" [Mathlib.Tactic.Bicategory.tacticBicategory_coherence](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Mathlib.Tactic.Bicategory.tacticBicategory_coherence)\n\nClose the goal of the form `η = θ`, where `η` and `θ` are 2-isomorphisms made up only of\nassociators, unitors, and identities.\n```lean\nexample {B : Type} [Bicategory B] {a : B} :\n  (λ_ (𝟙 a)).hom = (ρ_ (𝟙 a)).hom := by\n  bicategory_coherence\n```\n\n# \"bicategory_nf\" [Mathlib.Tactic.Bicategory.tacticBicategory_nf](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Mathlib.Tactic.Bicategory.tacticBicategory_nf)\n\nNormalize the both sides of an equality.\n\n# \"bitwise_assoc_tac\" [Nat.tacticBitwise_assoc_tac](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Nat.tacticBitwise_assoc_tac)\n\nProving associativity of bitwise operations in general essentially boils down to a huge case\ndistinction, so it is shorter to use this tactic instead of proving it in the general case.\n\n# \"borelize\" [Mathlib.Tactic.Borelize.tacticBorelize___](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Mathlib.Tactic.Borelize.tacticBorelize___)\n\nThe behaviour of `borelize α` depends on the existing assumptions on `α`.\n\n- if `α` is a topological space with instances `[MeasurableSpace α] [BorelSpace α]`, then\n  `borelize α` replaces the former instance by `borel α`;\n- otherwise, `borelize α` adds instances `borel α : MeasurableSpace α` and `⟨rfl⟩ : BorelSpace α`.\n\nFinally, `borelize α β γ` runs `borelize α; borelize β; borelize γ`.\n\n# \"bound\" [«tacticBound[_]»](https://leanprover-community.github.io/mathlib4_docs/search.html?q=«tacticBound[_]»)\n\n`bound` tactic for proving inequalities via straightforward recursion on expression structure.\n\nAn example use case is\n\n```\n-- Calc example: A weak lower bound for `z ↦ z^2 + c`\nlemma le_sqr_add {c z : ℂ} (cz : abs c ≤ abs z) (z3 : 3 ≤ abs z) :\n    2 * abs z ≤ abs (z^2 + c) := by\n  calc abs (z^2 + c)\n    _ ≥ abs (z^2) - abs c := by bound\n    _ ≥ abs (z^2) - abs z := by bound\n    _ ≥ (abs z - 1) * abs z := by rw [mul_comm, mul_sub_one, ← pow_two, ← abs.map_pow]\n    _ ≥ 2 * abs z := by bound\n```\n\n`bound` is built on top of `aesop`, and uses\n1. Apply lemmas registered via the `@[bound]` attribute\n2. Forward lemmas registered via the `@[bound_forward]` attribute\n3. Local hypotheses from the context\n4. Optionally: additional hypotheses provided as `bound [h₀, h₁]` or similar. These are added to the\n   context as if by `have := hᵢ`.\n\nThe functionality of `bound` overlaps with `positivity` and `gcongr`, but can jump back and forth\nbetween `0 ≤ x` and `x ≤ y`-type inequalities.  For example, `bound` proves\n  `0 ≤ c → b ≤ a → 0 ≤ a * c - b * c`\nby turning the goal into `b * c ≤ a * c`, then using `mul_le_mul_of_nonneg_right`.  `bound` also\ncontains lemmas for goals of the form `1 ≤ x, 1 \u003c x, x ≤ 1, x \u003c 1`.  Conversely, `gcongr` can prove\ninequalities for more types of relations, supports all `positivity` functionality, and is likely\nfaster since it is more specialized (not built atop `aesop`).\n\n# \"bv_check\" [Parser.Tactic.bvCheck](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Parser.Tactic.bvCheck)\n\nThis tactic works just like `bv_decide` but skips calling a SAT solver by using a proof that is\nalready stored on disk. It is called with the name of an LRAT file in the same directory as the\ncurrent Lean file:\n```\nbv_check \"proof.lrat\"\n```\n\n# \"bv_decide\" [Parser.Tactic.bvDecide](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Parser.Tactic.bvDecide)\n\nClose fixed-width `BitVec` and `Bool` goals by obtaining a proof from an external SAT solver and\nverifying it inside Lean. The solvable goals are currently limited to the Lean equivalent of\n[`QF_BV`](https://smt-lib.org/logics-all.shtml#QF_BV):\n```lean\nexample : ∀ (a b : BitVec 64), (a \u0026\u0026\u0026 b) + (a ^^^ b) = a ||| b := by\n  intros\n  bv_decide\n```\n\nIf `bv_decide` encounters an unknown definition it will be treated like an unconstrained `BitVec`\nvariable. Sometimes this enables solving goals despite not understanding the definition because\nthe precise properties of the definition do not matter in the specific proof.\n\nIf `bv_decide` fails to close a goal it provides a counter-example, containing assignments for all\nterms that were considered as variables.\n\nIn order to avoid calling a SAT solver every time, the proof can be cached with `bv_decide?`.\n\nIf solving your problem relies inherently on using associativity or commutativity, consider enabling\nthe `bv.ac_nf` option.\n\n\nNote: `bv_decide` uses `ofReduceBool` and thus trusts the correctness of the code generator.\n\n# \"bv_decide?\" [Parser.Tactic.bvTrace](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Parser.Tactic.bvTrace)\n\nSuggest a proof script for a `bv_decide` tactic call. Useful for caching LRAT proofs.\n\n# \"bv_normalize\" [Parser.Tactic.bvNormalize](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Parser.Tactic.bvNormalize)\n\nRun the normalization procedure of `bv_decide` only. Sometimes this is enough to solve basic\n`BitVec` goals already.\n\n# \"bv_omega\" [Parser.Tactic.tacticBv_omega](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Parser.Tactic.tacticBv_omega)\n\n`bv_omega` is `omega` with an additional preprocessor that turns statements about `BitVec` into statements about `Nat`.\nCurrently the preprocessor is implemented as `try simp only [bv_toNat] at *`.\n`bv_toNat` is a `@[simp]` attribute that you can (cautiously) add to more theorems.\n\n# \"by_cases\" [«tacticBy_cases_:_»](https://leanprover-community.github.io/mathlib4_docs/search.html?q=«tacticBy_cases_:_»)\n\n`by_cases (h :)? p` splits the main goal into two cases, assuming `h : p` in the first branch, and `h : ¬ p` in the second branch.\n\n# \"by_contra\" [Batteries.Tactic.byContra](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Batteries.Tactic.byContra)\n\n`by_contra h` proves `⊢ p` by contradiction,\nintroducing a hypothesis `h : ¬p` and proving `False`.\n* If `p` is a negation `¬q`, `h : q` will be introduced instead of `¬¬q`.\n* If `p` is decidable, it uses `Decidable.byContradiction` instead of `Classical.byContradiction`.\n* If `h` is omitted, the introduced variable `_: ¬p` will be anonymous.\n\n# \"by_contra!\" [byContra!](https://leanprover-community.github.io/mathlib4_docs/search.html?q=byContra!)\n\nIf the target of the main goal is a proposition `p`,\n`by_contra!` reduces the goal to proving `False` using the additional hypothesis `this : ¬ p`.\n`by_contra! h` can be used to name the hypothesis `h : ¬ p`.\nThe hypothesis `¬ p` will be negation normalized using `push_neg`.\nFor instance, `¬ a \u003c b` will be changed to `b ≤ a`.\n`by_contra! h : q` will normalize negations in `¬ p`, normalize negations in `q`,\nand then check that the two normalized forms are equal.\nThe resulting hypothesis is the pre-normalized form, `q`.\nIf the name `h` is not explicitly provided, then `this` will be used as name.\nThis tactic uses classical reasoning.\nIt is a variant on the tactic `by_contra`.\nExamples:\n```lean\nexample : 1 \u003c 2 := by\n  by_contra! h\n  -- h : 2 ≤ 1 ⊢ False\n\nexample : 1 \u003c 2 := by\n  by_contra! h : ¬ 1 \u003c 2\n  -- h : ¬ 1 \u003c 2 ⊢ False\n```\n\n# \"calc\" [calcTactic](https://leanprover-community.github.io/mathlib4_docs/search.html?q=calcTactic)\n\nStep-wise reasoning over transitive relations.\n```\ncalc\n  a = b := pab\n  b = c := pbc\n  ...\n  y = z := pyz\n```\nproves `a = z` from the given step-wise proofs. `=` can be replaced with any\nrelation implementing the typeclass `Trans`. Instead of repeating the right-\nhand sides, subsequent left-hand sides can be replaced with `_`.\n```\ncalc\n  a = b := pab\n  _ = c := pbc\n  ...\n  _ = z := pyz\n```\nIt is also possible to write the *first* relation as `\u003clhs\u003e\\n  _ = \u003crhs\u003e :=\n\u003cproof\u003e`. This is useful for aligning relation symbols, especially on longer:\nidentifiers:\n```\ncalc abc\n  _ = bce := pabce\n  _ = cef := pbcef\n  ...\n  _ = xyz := pwxyz\n```\n\n`calc` works as a term, as a tactic or as a `conv` tactic.\n\nSee [Theorem Proving in Lean 4][tpil4] for more information.\n\n[tpil4]: https://lean-lang.org/theorem_proving_in_lean4/quantifiers_and_equality.html#calculational-proofs\n\n# \"cancel_denoms\" [tacticCancel_denoms_](https://leanprover-community.github.io/mathlib4_docs/search.html?q=tacticCancel_denoms_)\n\n\n# \"cancel_denoms\" [cancelDenoms](https://leanprover-community.github.io/mathlib4_docs/search.html?q=cancelDenoms)\n\n`cancel_denoms` attempts to remove numerals from the denominators of fractions.\nIt works on propositions that are field-valued inequalities.\n\n```lean\nvariable [LinearOrderedField α] (a b c : α)\n\nexample (h : a / 5 + b / 4 \u003c c) : 4*a + 5*b \u003c 20*c := by\n  cancel_denoms at h\n  exact h\n\nexample (h : a \u003e 0) : a / 5 \u003e 0 := by\n  cancel_denoms\n  exact h\n```\n\n# \"case\" [Parser.Tactic.case](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Parser.Tactic.case)\n\n* `case tag =\u003e tac` focuses on the goal with case name `tag` and solves it using `tac`,\n  or else fails.\n* `case tag x₁ ... xₙ =\u003e tac` additionally renames the `n` most recent hypotheses\n  with inaccessible names to the given names.\n* `case tag₁ | tag₂ =\u003e tac` is equivalent to `(case tag₁ =\u003e tac); (case tag₂ =\u003e tac)`.\n\n# \"case'\" [Parser.Tactic.case'](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Parser.Tactic.case')\n\n`case'` is similar to the `case tag =\u003e tac` tactic, but does not ensure the goal\nhas been solved after applying `tac`, nor admits the goal if `tac` failed.\nRecall that `case` closes the goal using `sorry` when `tac` fails, and\nthe tactic execution is not interrupted.\n\n# \"cases\" [Parser.Tactic.cases](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Parser.Tactic.cases)\n\nAssuming `x` is a variable in the local context with an inductive type,\n`cases x` splits the main goal, producing one goal for each constructor of the\ninductive type, in which the target is replaced by a general instance of that constructor.\nIf the type of an element in the local context depends on `x`,\nthat element is reverted and reintroduced afterward,\nso that the case split affects that hypothesis as well.\n`cases` detects unreachable cases and closes them automatically.\n\nFor example, given `n : Nat` and a goal with a hypothesis `h : P n` and target `Q n`,\n`cases n` produces one goal with hypothesis `h : P 0` and target `Q 0`,\nand one goal with hypothesis `h : P (Nat.succ a)` and target `Q (Nat.succ a)`.\nHere the name `a` is chosen automatically and is not accessible.\nYou can use `with` to provide the variables names for each constructor.\n- `cases e`, where `e` is an expression instead of a variable, generalizes `e` in the goal,\n  and then cases on the resulting variable.\n- Given `as : List α`, `cases as with | nil =\u003e tac₁ | cons a as' =\u003e tac₂`,\n  uses tactic `tac₁` for the `nil` case, and `tac₂` for the `cons` case,\n  and `a` and `as'` are used as names for the new variables introduced.\n- `cases h : e`, where `e` is a variable or an expression,\n  performs cases on `e` as above, but also adds a hypothesis `h : e = ...` to each hypothesis,\n  where `...` is the constructor instance for that particular case.\n\n# \"cases'\" [Mathlib.Tactic.cases'](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Mathlib.Tactic.cases')\n\nThe `cases'` tactic is similar to the `cases` tactic in Lean 4 core, but the syntax for giving\nnames is different:\n\n```\nexample (h : p ∨ q) : q ∨ p := by\n  cases h with\n  | inl hp =\u003e exact Or.inr hp\n  | inr hq =\u003e exact Or.inl hq\n\nexample (h : p ∨ q) : q ∨ p := by\n  cases' h with hp hq\n  · exact Or.inr hp\n  · exact Or.inl hq\n\nexample (h : p ∨ q) : q ∨ p := by\n  rcases h with hp | hq\n  · exact Or.inr hp\n  · exact Or.inl hq\n```\n\nPrefer `cases` or `rcases` when possible, because these tactics promote structured proofs.\n\n# \"cases_type\" [Mathlib.Tactic.casesType](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Mathlib.Tactic.casesType)\n\n* `cases_type I` applies the `cases` tactic to a hypothesis `h : (I ...)`\n* `cases_type I_1 ... I_n` applies the `cases` tactic to a hypothesis\n  `h : (I_1 ...)` or ... or `h : (I_n ...)`\n* `cases_type* I` is shorthand for `· repeat cases_type I`\n* `cases_type! I` only applies `cases` if the number of resulting subgoals is \u003c= 1.\n\nExample: The following tactic destructs all conjunctions and disjunctions in the current goal.\n```\ncases_type* Or And\n```\n\n# \"cases_type!\" [Mathlib.Tactic.casesType!](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Mathlib.Tactic.casesType!)\n\n* `cases_type I` applies the `cases` tactic to a hypothesis `h : (I ...)`\n* `cases_type I_1 ... I_n` applies the `cases` tactic to a hypothesis\n  `h : (I_1 ...)` or ... or `h : (I_n ...)`\n* `cases_type* I` is shorthand for `· repeat cases_type I`\n* `cases_type! I` only applies `cases` if the number of resulting subgoals is \u003c= 1.\n\nExample: The following tactic destructs all conjunctions and disjunctions in the current goal.\n```\ncases_type* Or And\n```\n\n# \"casesm\" [Mathlib.Tactic.casesM](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Mathlib.Tactic.casesM)\n\n* `casesm p` applies the `cases` tactic to a hypothesis `h : type`\n  if `type` matches the pattern `p`.\n* `casesm p_1, ..., p_n` applies the `cases` tactic to a hypothesis `h : type`\n  if `type` matches one of the given patterns.\n* `casesm* p` is a more efficient and compact version of `· repeat casesm p`.\n  It is more efficient because the pattern is compiled once.\n\nExample: The following tactic destructs all conjunctions and disjunctions in the current context.\n```\ncasesm* _ ∨ _, _ ∧ _\n```\n\n# \"cc\" [Mathlib.Tactic.cc](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Mathlib.Tactic.cc)\n\nThe congruence closure tactic `cc` tries to solve the goal by chaining\nequalities from context and applying congruence (i.e. if `a = b`, then `f a = f b`).\nIt is a finishing tactic, i.e. it is meant to close\nthe current goal, not to make some inconclusive progress.\nA mostly trivial example would be:\n\n```lean\nexample (a b c : ℕ) (f : ℕ → ℕ) (h: a = b) (h' : b = c) : f a = f c := by\n  cc\n```\n\nAs an example requiring some thinking to do by hand, consider:\n\n```lean\nexample (f : ℕ → ℕ) (x : ℕ)\n    (H1 : f (f (f x)) = x) (H2 : f (f (f (f (f x)))) = x) :\n    f x = x := by\n  cc\n```\n\n# \"cfc_cont_tac\" [cfcContTac](https://leanprover-community.github.io/mathlib4_docs/search.html?q=cfcContTac)\n\nA tactic used to automatically discharge goals relating to the continuous functional calculus,\nspecifically concerning continuity of the functions involved.\n\n# \"cfc_tac\" [cfcTac](https://leanprover-community.github.io/mathlib4_docs/search.html?q=cfcTac)\n\nA tactic used to automatically discharge goals relating to the continuous functional calculus,\nspecifically whether the element satisfies the predicate.\n\n# \"cfc_zero_tac\" [cfcZeroTac](https://leanprover-community.github.io/mathlib4_docs/search.html?q=cfcZeroTac)\n\nA tactic used to automatically discharge goals relating to the non-unital continuous functional\ncalculus, specifically concerning whether `f 0 = 0`.\n\n# \"change\" [Parser.Tactic.change](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Parser.Tactic.change)\n\n* `change tgt'` will change the goal from `tgt` to `tgt'`,\n  assuming these are definitionally equal.\n* `change t' at h` will change hypothesis `h : t` to have type `t'`, assuming\n  assuming `t` and `t'` are definitionally equal.\n\n# \"change\" [Parser.Tactic.changeWith](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Parser.Tactic.changeWith)\n\n* `change a with b` will change occurrences of `a` to `b` in the goal,\n  assuming `a` and `b` are definitionally equal.\n* `change a with b at h` similarly changes `a` to `b` in the type of hypothesis `h`.\n\n# \"change?\" [change?](https://leanprover-community.github.io/mathlib4_docs/search.html?q=change?)\n\n`change? term` unifies `term` with the current goal, then suggests explicit `change` syntax\nthat uses the resulting unified term.\n\nIf `term` is not present, `change?` suggests the current goal itself. This is useful after tactics\nwhich transform the goal while maintaining definitional equality, such as `dsimp`; those preceding\ntactic calls can then be deleted.\n```lean\nexample : (fun x : Nat =\u003e x) 0 = 1 := by\n  change? 0 = _  -- `Try this: change 0 = 1`\n```\n\n# \"checkpoint\" [Parser.Tactic.checkpoint](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Parser.Tactic.checkpoint)\n\n`checkpoint tac` acts the same as `tac`, but it caches the input and output of `tac`,\nand if the file is re-elaborated and the input matches, the tactic is not re-run and\nits effects are reapplied to the state. This is useful for improving responsiveness\nwhen working on a long tactic proof, by wrapping expensive tactics with `checkpoint`.\n\nSee the `save` tactic, which may be more convenient to use.\n\n(TODO: do this automatically and transparently so that users don't have to use\nthis combinator explicitly.)\n\n# \"choose\" [Mathlib.Tactic.Choose.choose](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Mathlib.Tactic.Choose.choose)\n\n* `choose a b h h' using hyp` takes a hypothesis `hyp` of the form\n  `∀ (x : X) (y : Y), ∃ (a : A) (b : B), P x y a b ∧ Q x y a b`\n  for some `P Q : X → Y → A → B → Prop` and outputs\n  into context a function `a : X → Y → A`, `b : X → Y → B` and two assumptions:\n  `h : ∀ (x : X) (y : Y), P x y (a x y) (b x y)` and\n  `h' : ∀ (x : X) (y : Y), Q x y (a x y) (b x y)`. It also works with dependent versions.\n\n* `choose! a b h h' using hyp` does the same, except that it will remove dependency of\n  the functions on propositional arguments if possible. For example if `Y` is a proposition\n  and `A` and `B` are nonempty in the above example then we will instead get\n  `a : X → A`, `b : X → B`, and the assumptions\n  `h : ∀ (x : X) (y : Y), P x y (a x) (b x)` and\n  `h' : ∀ (x : X) (y : Y), Q x y (a x) (b x)`.\n\nThe `using hyp` part can be omitted,\nwhich will effectively cause `choose` to start with an `intro hyp`.\n\nExamples:\n\n```\nexample (h : ∀ n m : ℕ, ∃ i j, m = n + i ∨ m + j = n) : True := by\n  choose i j h using h\n  guard_hyp i : ℕ → ℕ → ℕ\n  guard_hyp j : ℕ → ℕ → ℕ\n  guard_hyp h : ∀ (n m : ℕ), m = n + i n m ∨ m + j n m = n\n  trivial\n```\n\n```\nexample (h : ∀ i : ℕ, i \u003c 7 → ∃ j, i \u003c j ∧ j \u003c i+i) : True := by\n  choose! f h h' using h\n  guard_hyp f : ℕ → ℕ\n  guard_hyp h : ∀ (i : ℕ), i \u003c 7 → i \u003c f i\n  guard_hyp h' : ∀ (i : ℕ), i \u003c 7 → f i \u003c i + i\n  trivial\n```\n\n# \"choose!\" [Mathlib.Tactic.Choose.tacticChoose!___Using_](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Mathlib.Tactic.Choose.tacticChoose!___Using_)\n\n* `choose a b h h' using hyp` takes a hypothesis `hyp` of the form\n  `∀ (x : X) (y : Y), ∃ (a : A) (b : B), P x y a b ∧ Q x y a b`\n  for some `P Q : X → Y → A → B → Prop` and outputs\n  into context a function `a : X → Y → A`, `b : X → Y → B` and two assumptions:\n  `h : ∀ (x : X) (y : Y), P x y (a x y) (b x y)` and\n  `h' : ∀ (x : X) (y : Y), Q x y (a x y) (b x y)`. It also works with dependent versions.\n\n* `choose! a b h h' using hyp` does the same, except that it will remove dependency of\n  the functions on propositional arguments if possible. For example if `Y` is a proposition\n  and `A` and `B` are nonempty in the above example then we will instead get\n  `a : X → A`, `b : X → B`, and the assumptions\n  `h : ∀ (x : X) (y : Y), P x y (a x) (b x)` and\n  `h' : ∀ (x : X) (y : Y), Q x y (a x) (b x)`.\n\nThe `using hyp` part can be omitted,\nwhich will effectively cause `choose` to start with an `intro hyp`.\n\nExamples:\n\n```\nexample (h : ∀ n m : ℕ, ∃ i j, m = n + i ∨ m + j = n) : True := by\n  choose i j h using h\n  guard_hyp i : ℕ → ℕ → ℕ\n  guard_hyp j : ℕ → ℕ → ℕ\n  guard_hyp h : ∀ (n m : ℕ), m = n + i n m ∨ m + j n m = n\n  trivial\n```\n\n```\nexample (h : ∀ i : ℕ, i \u003c 7 → ∃ j, i \u003c j ∧ j \u003c i+i) : True := by\n  choose! f h h' using h\n  guard_hyp f : ℕ → ℕ\n  guard_hyp h : ∀ (i : ℕ), i \u003c 7 → i \u003c f i\n  guard_hyp h' : ∀ (i : ℕ), i \u003c 7 → f i \u003c i + i\n  trivial\n```\n\n# \"classical\" [Parser.Tactic.classical](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Parser.Tactic.classical)\n\n`classical tacs` runs `tacs` in a scope where `Classical.propDecidable` is a low priority\nlocal instance.\n\nNote that `classical` is a scoping tactic: it adds the instance only within the\nscope of the tactic.\n\n# \"clean\" [Mathlib.Tactic.tacticClean_](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Mathlib.Tactic.tacticClean_)\n\n(Deprecated) `clean t` is a macro for `exact clean% t`.\n\n# \"clean_wf\" [tacticClean_wf](https://leanprover-community.github.io/mathlib4_docs/search.html?q=tacticClean_wf)\n\nThis tactic is used internally by lean before presenting the proof obligations from a well-founded\ndefinition to the user via `decreasing_by`. It is not necessary to use this tactic manually.\n\n# \"clear\" [clearExcept](https://leanprover-community.github.io/mathlib4_docs/search.html?q=clearExcept)\n\nClears all hypotheses it can, except those provided after a minus sign. Example:\n```\n  clear * - h₁ h₂\n```\n\n# \"clear\" [Parser.Tactic.clear](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Parser.Tactic.clear)\n\n`clear x...` removes the given hypotheses, or fails if there are remaining\nreferences to a hypothesis.\n\n# \"clear!\" [Mathlib.Tactic.clear!](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Mathlib.Tactic.clear!)\n\nA variant of `clear` which clears not only the given hypotheses but also any other hypotheses\ndepending on them\n\n# \"clear_\" [Mathlib.Tactic.clear_](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Mathlib.Tactic.clear_)\n\nClear all hypotheses starting with `_`, like `_match` and `_let_match`.\n\n# \"clear_aux_decl\" [Mathlib.Tactic.clearAuxDecl](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Mathlib.Tactic.clearAuxDecl)\n\nThis tactic clears all auxiliary declarations from the context.\n\n# \"clear_value\" [Mathlib.Tactic.clearValue](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Mathlib.Tactic.clearValue)\n\n`clear_value n₁ n₂ ...` clears the bodies of the local definitions `n₁, n₂ ...`, changing them\ninto regular hypotheses. A hypothesis `n : α := t` is changed to `n : α`.\n\nThe order of `n₁ n₂ ...` does not matter, and values will be cleared in reverse order of\nwhere they appear in the context.\n\n# \"coherence\" [Mathlib.Tactic.Coherence.coherence](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Mathlib.Tactic.Coherence.coherence)\n\nUse the coherence theorem for monoidal categories to solve equations in a monoidal equation,\nwhere the two sides only differ by replacing strings of monoidal structural morphisms\n(that is, associators, unitors, and identities)\nwith different strings of structural morphisms with the same source and target.\n\nThat is, `coherence` can handle goals of the form\n`a ≫ f ≫ b ≫ g ≫ c = a' ≫ f ≫ b' ≫ g ≫ c'`\nwhere `a = a'`, `b = b'`, and `c = c'` can be proved using `pure_coherence`.\n\n(If you have very large equations on which `coherence` is unexpectedly failing,\nyou may need to increase the typeclass search depth,\nusing e.g. `set_option synthInstance.maxSize 500`.)\n\n# \"compareOfLessAndEq_rfl\" [tacticCompareOfLessAndEq_rfl](https://leanprover-community.github.io/mathlib4_docs/search.html?q=tacticCompareOfLessAndEq_rfl)\n\nThis attempts to prove that a given instance of `compare` is equal to `compareOfLessAndEq` by\nintroducing the arguments and trying the following approaches in order:\n\n1. seeing if `rfl` works\n2. seeing if the `compare` at hand is nonetheless essentially `compareOfLessAndEq`, but, because of\nimplicit arguments, requires us to unfold the defs and split the `if`s in the definition of\n`compareOfLessAndEq`\n3. seeing if we can split by cases on the arguments, then see if the defs work themselves out\n  (useful when `compare` is defined via a `match` statement, as it is for `Bool`)\n\n# \"compute_degree\" [Mathlib.Tactic.ComputeDegree.computeDegree](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Mathlib.Tactic.ComputeDegree.computeDegree)\n\n`compute_degree` is a tactic to solve goals of the form\n*  `natDegree f = d`,\n*  `degree f = d`,\n*  `natDegree f ≤ d`,\n*  `degree f ≤ d`,\n*  `coeff f d = r`, if `d` is the degree of `f`.\n\nThe tactic may leave goals of the form `d' = d` `d' ≤ d`, or `r ≠ 0`, where `d'` in `ℕ` or\n`WithBot ℕ` is the tactic's guess of the degree, and `r` is the coefficient's guess of the\nleading coefficient of `f`.\n\n`compute_degree` applies `norm_num` to the left-hand side of all side goals, trying to close them.\n\nThe variant `compute_degree!` first applies `compute_degree`.\nThen it uses `norm_num` on all the whole remaining goals and tries `assumption`.\n\n# \"compute_degree!\" [Mathlib.Tactic.ComputeDegree.tacticCompute_degree!](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Mathlib.Tactic.ComputeDegree.tacticCompute_degree!)\n\n`compute_degree` is a tactic to solve goals of the form\n*  `natDegree f = d`,\n*  `degree f = d`,\n*  `natDegree f ≤ d`,\n*  `degree f ≤ d`,\n*  `coeff f d = r`, if `d` is the degree of `f`.\n\nThe tactic may leave goals of the form `d' = d` `d' ≤ d`, or `r ≠ 0`, where `d'` in `ℕ` or\n`WithBot ℕ` is the tactic's guess of the degree, and `r` is the coefficient's guess of the\nleading coefficient of `f`.\n\n`compute_degree` applies `norm_num` to the left-hand side of all side goals, trying to close them.\n\nThe variant `compute_degree!` first applies `compute_degree`.\nThen it uses `norm_num` on all the whole remaining goals and tries `assumption`.\n\n# \"congr\" [Parser.Tactic.congr](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Parser.Tactic.congr)\n\nApply congruence (recursively) to goals of the form `⊢ f as = f bs` and `⊢ HEq (f as) (f bs)`.\nThe optional parameter is the depth of the recursive applications.\nThis is useful when `congr` is too aggressive in breaking down the goal.\nFor example, given `⊢ f (g (x + y)) = f (g (y + x))`,\n`congr` produces the goals `⊢ x = y` and `⊢ y = x`,\nwhile `congr 2` produces the intended `⊢ x + y = y + x`.\n\n# \"congr\" [Batteries.Tactic.congrConfigWith](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Batteries.Tactic.congrConfigWith)\n\nApply congruence (recursively) to goals of the form `⊢ f as = f bs` and `⊢ HEq (f as) (f bs)`.\n* `congr n` controls the depth of the recursive applications.\n  This is useful when `congr` is too aggressive in breaking down the goal.\n  For example, given `⊢ f (g (x + y)) = f (g (y + x))`,\n  `congr` produces the goals `⊢ x = y` and `⊢ y = x`,\n  while `congr 2` produces the intended `⊢ x + y = y + x`.\n* If, at any point, a subgoal matches a hypothesis then the subgoal will be closed.\n* You can use `congr with p (: n)?` to call `ext p (: n)?` to all subgoals generated by `congr`.\n  For example, if the goal is `⊢ f '' s = g '' s` then `congr with x` generates the goal\n  `x : α ⊢ f x = g x`.\n\n# \"congr\" [Batteries.Tactic.congrConfig](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Batteries.Tactic.congrConfig)\n\nApply congruence (recursively) to goals of the form `⊢ f as = f bs` and `⊢ HEq (f as) (f bs)`.\nThe optional parameter is the depth of the recursive applications.\nThis is useful when `congr` is too aggressive in breaking down the goal.\nFor example, given `⊢ f (g (x + y)) = f (g (y + x))`,\n`congr` produces the goals `⊢ x = y` and `⊢ y = x`,\nwhile `congr 2` produces the intended `⊢ x + y = y + x`.\n\n# \"congr!\" [Congr!.congr!](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Congr!.congr!)\n\nEquates pieces of the left-hand side of a goal to corresponding pieces of the right-hand side by\nrecursively applying congruence lemmas. For example, with `⊢ f as = g bs` we could get\ntwo goals `⊢ f = g` and `⊢ as = bs`.\n\nSyntax:\n```\ncongr!\ncongr! n\ncongr! with x y z\ncongr! n with x y z\n```\nHere, `n` is a natural number and `x`, `y`, `z` are `rintro` patterns (like `h`, `rfl`, `⟨x, y⟩`,\n`_`, `-`, `(h | h)`, etc.).\n\nThe `congr!` tactic is similar to `congr` but is more insistent in trying to equate left-hand sides\nto right-hand sides of goals. Here is a list of things it can try:\n\n- If `R` in `⊢ R x y` is a reflexive relation, it will convert the goal to `⊢ x = y` if possible.\n  The list of reflexive relations is maintained using the `@[refl]` attribute.\n  As a special case, `⊢ p ↔ q` is converted to `⊢ p = q` during congruence processing and then\n  returned to `⊢ p ↔ q` form at the end.\n\n- If there is a user congruence lemma associated to the goal (for instance, a `@[congr]`-tagged\n  lemma applying to `⊢ List.map f xs = List.map g ys`), then it will use that.\n\n- It uses a congruence lemma generator at least as capable as the one used by `congr` and `simp`.\n  If there is a subexpression that can be rewritten by `simp`, then `congr!` should be able\n  to generate an equality for it.\n\n- It can do congruences of pi types using lemmas like `implies_congr` and `pi_congr`.\n\n- Before applying congruences, it will run the `intros` tactic automatically.\n  The introduced variables can be given names using a `with` clause.\n  This helps when congruence lemmas provide additional assumptions in hypotheses.\n\n- When there is an equality between functions, so long as at least one is obviously a lambda, we\n  apply `funext` or `Function.hfunext`, which allows for congruence of lambda bodies.\n\n- It can try to close goals using a few strategies, including checking\n  definitional equality, trying to apply `Subsingleton.elim` or `proof_irrel_heq`, and using the\n  `assumption` tactic.\n\nThe optional parameter is the depth of the recursive applications.\nThis is useful when `congr!` is too aggressive in breaking down the goal.\nFor example, given `⊢ f (g (x + y)) = f (g (y + x))`,\n`congr!` produces the goals `⊢ x = y` and `⊢ y = x`,\nwhile `congr! 2` produces the intended `⊢ x + y = y + x`.\n\nThe `congr!` tactic also takes a configuration option, for example\n```lean\ncongr! (config := {transparency := .default}) 2\n```\nThis overrides the default, which is to apply congruence lemmas at reducible transparency.\n\nThe `congr!` tactic is aggressive with equating two sides of everything. There is a predefined\nconfiguration that uses a different strategy:\nTry\n```lean\ncongr! (config := .unfoldSameFun)\n```\nThis only allows congruences between functions applications of definitionally equal functions,\nand it applies congruence lemmas at default transparency (rather than just reducible).\nThis is somewhat like `congr`.\n\nSee `Congr!.Config` for all options.\n\n# \"congrm\" [Mathlib.Tactic.congrM](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Mathlib.Tactic.congrM)\n\n`congrm e` is a tactic for proving goals of the form `lhs = rhs`, `lhs ↔ rhs`, `HEq lhs rhs`,\nor `R lhs rhs` when `R` is a reflexive relation.\nThe expression `e` is a pattern containing placeholders `?_`,\nand this pattern is matched against `lhs` and `rhs` simultaneously.\nThese placeholders generate new goals that state that corresponding subexpressions\nin `lhs` and `rhs` are equal.\nIf the placeholders have names, such as `?m`, then the new goals are given tags with those names.\n\nExamples:\n```lean\nexample {a b c d : ℕ} :\n    Nat.pred a.succ * (d + (c + a.pred)) = Nat.pred b.succ * (b + (c + d.pred)) := by\n  congrm Nat.pred (Nat.succ ?h1) * (?h2 + ?h3)\n  /-  Goals left:\n  case h1 ⊢ a = b\n  case h2 ⊢ d = b\n  case h3 ⊢ c + a.pred = c + d.pred\n  -/\n  sorry\n  sorry\n  sorry\n\nexample {a b : ℕ} (h : a = b) : (fun y : ℕ =\u003e ∀ z, a + a = z) = (fun x =\u003e ∀ z, b + a = z) := by\n  congrm fun x =\u003e ∀ w, ?_ + a = w\n  -- ⊢ a = b\n  exact h\n```\n\nThe `congrm` command is a convenient frontend to `congr(...)` congruence quotations.\nIf the goal is an equality, `congrm e` is equivalent to `refine congr(e')` where `e'` is\nbuilt from `e` by replacing each placeholder `?m` by `$(?m)`.\nThe pattern `e` is allowed to contain `$(...)` expressions to immediately substitute\nequality proofs into the congruence, just like for congruence quotations.\n\n# \"congrm?\" [tacticCongrm?](https://leanprover-community.github.io/mathlib4_docs/search.html?q=tacticCongrm?)\n\nDisplay a widget panel allowing to generate a `congrm` call with holes specified by selecting\nsubexpressions in the goal.\n\n# \"constructor\" [Parser.Tactic.constructor](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Parser.Tactic.constructor)\n\nIf the main goal's target type is an inductive type, `constructor` solves it with\nthe first matching constructor, or else fails.\n\n# \"constructorm\" [Mathlib.Tactic.constructorM](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Mathlib.Tactic.constructorM)\n\n* `constructorm p_1, ..., p_n` applies the `constructor` tactic to the main goal\n  if `type` matches one of the given patterns.\n* `constructorm* p` is a more efficient and compact version of `· repeat constructorm p`.\n  It is more efficient because the pattern is compiled once.\n\nExample: The following tactic proves any theorem like `True ∧ (True ∨ True)` consisting of\nand/or/true:\n```\nconstructorm* _ ∨ _, _ ∧ _, True\n```\n\n# \"continuity\" [tacticContinuity](https://leanprover-community.github.io/mathlib4_docs/search.html?q=tacticContinuity)\n\nThe tactic `continuity` solves goals of the form `Continuous f` by applying lemmas tagged with the\n`continuity` user attribute.\n\n# \"continuity?\" [tacticContinuity?](https://leanprover-community.github.io/mathlib4_docs/search.html?q=tacticContinuity?)\n\nThe tactic `continuity` solves goals of the form `Continuous f` by applying lemmas tagged with the\n`continuity` user attribute.\n\n# \"contradiction\" [Parser.Tactic.contradiction](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Parser.Tactic.contradiction)\n\n`contradiction` closes the main goal if its hypotheses are \"trivially contradictory\".\n\n- Inductive type/family with no applicable constructors\n  ```lean\n  example (h : False) : p := by contradiction\n  ```\n- Injectivity of constructors\n  ```lean\n  example (h : none = some true) : p := by contradiction  --\n  ```\n- Decidable false proposition\n  ```lean\n  example (h : 2 + 2 = 3) : p := by contradiction\n  ```\n- Contradictory hypotheses\n  ```lean\n  example (h : p) (h' : ¬ p) : q := by contradiction\n  ```\n- Other simple contradictions such as\n  ```lean\n  example (x : Nat) (h : x ≠ x) : p := by contradiction\n  ```\n\n# \"contrapose\" [Mathlib.Tactic.Contrapose.contrapose](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Mathlib.Tactic.Contrapose.contrapose)\n\nTransforms the goal into its contrapositive.\n* `contrapose`     turns a goal `P → Q` into `¬ Q → ¬ P`\n* `contrapose h`   first reverts the local assumption `h`, and then uses `contrapose` and `intro h`\n* `contrapose h with new_h` uses the name `new_h` for the introduced hypothesis\n\n# \"contrapose!\" [Mathlib.Tactic.Contrapose.contrapose!](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Mathlib.Tactic.Contrapose.contrapose!)\n\nTransforms the goal into its contrapositive and uses pushes negations inside `P` and `Q`.\nUsage matches `contrapose`\n\n# \"conv\" [Parser.Tactic.Conv.conv](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Parser.Tactic.Conv.conv)\n\n`conv =\u003e ...` allows the user to perform targeted rewriting on a goal or hypothesis,\nby focusing on particular subexpressions.\n\nSee \u003chttps://lean-lang.org/theorem_proving_in_lean4/conv.html\u003e for more details.\n\nBasic forms:\n* `conv =\u003e cs` will rewrite the goal with conv tactics `cs`.\n* `conv at h =\u003e cs` will rewrite hypothesis `h`.\n* `conv in pat =\u003e cs` will rewrite the first subexpression matching `pat` (see `pattern`).\n\n# \"conv'\" [Parser.Tactic.Conv.convTactic](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Parser.Tactic.Conv.convTactic)\n\nExecutes the given conv block without converting regular goal into a `conv` goal.\n\n# \"conv?\" [tacticConv?](https://leanprover-community.github.io/mathlib4_docs/search.html?q=tacticConv?)\n\nDisplay a widget panel allowing to generate a `conv` call zooming to the subexpression selected\nin the goal.\n\n# \"conv_lhs\" [Mathlib.Tactic.Conv.convLHS](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Mathlib.Tactic.Conv.convLHS)\n\n\n# \"conv_rhs\" [Mathlib.Tactic.Conv.convRHS](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Mathlib.Tactic.Conv.convRHS)\n\n\n# \"convert\" [Mathlib.Tactic.convert](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Mathlib.Tactic.convert)\n\nThe `exact e` and `refine e` tactics require a term `e` whose type is\ndefinitionally equal to the goal. `convert e` is similar to `refine e`,\nbut the type of `e` is not required to exactly match the\ngoal. Instead, new goals are created for differences between the type\nof `e` and the goal using the same strategies as the `congr!` tactic.\nFor example, in the proof state\n\n```lean\nn : ℕ,\ne : Prime (2 * n + 1)\n⊢ Prime (n + n + 1)\n```\n\nthe tactic `convert e using 2` will change the goal to\n\n```lean\n⊢ n + n = 2 * n\n```\n\nIn this example, the new goal can be solved using `ring`.\n\nThe `using 2` indicates it should iterate the congruence algorithm up to two times,\nwhere `convert e` would use an unrestricted number of iterations and lead to two\nimpossible goals: `⊢ HAdd.hAdd = HMul.hMul` and `⊢ n = 2`.\n\nA variant configuration is `convert (config := .unfoldSameFun) e`, which only equates function\napplications for the same function (while doing so at the higher `default` transparency).\nThis gives the same goal of `⊢ n + n = 2 * n` without needing `using 2`.\n\nThe `convert` tactic applies congruence lemmas eagerly before reducing,\ntherefore it can fail in cases where `exact` succeeds:\n```lean\ndef p (n : ℕ) := True\nexample (h : p 0) : p 1 := by exact h -- succeeds\nexample (h : p 0) : p 1 := by convert h -- fails, with leftover goal `1 = 0`\n```\nLimiting the depth of recursion can help with this. For example, `convert h using 1` will work\nin this case.\n\nThe syntax `convert ← e` will reverse the direction of the new goals\n(producing `⊢ 2 * n = n + n` in this example).\n\nInternally, `convert e` works by creating a new goal asserting that\nthe goal equals the type of `e`, then simplifying it using\n`congr!`. The syntax `convert e using n` can be used to control the\ndepth of matching (like `congr! n`). In the example, `convert e using 1`\nwould produce a new goal `⊢ n + n + 1 = 2 * n + 1`.\n\nRefer to the `congr!` tactic to understand the congruence operations. One of its many\nfeatures is that if `x y : t` and an instance `Subsingleton t` is in scope,\nthen any goals of the form `x = y` are solved automatically.\n\nLike `congr!`, `convert` takes an optional `with` clause of `rintro` patterns,\nfor example `convert e using n with x y z`.\n\nThe `convert` tactic also takes a configuration option, for example\n```lean\nconvert (config := {transparency := .default}) h\n```\nThese are passed to `congr!`. See `Congr!.Config` for options.\n\n# \"convert_to\" [Mathlib.Tactic.convertTo](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Mathlib.Tactic.convertTo)\n\nThe `convert_to` tactic is for changing the type of the target or a local hypothesis,\nbut unlike the `change` tactic it will generate equality proof obligations using `congr!`\nto resolve discrepancies.\n\n* `convert_to ty` changes the target to `ty`\n* `convert_to ty using n` uses `congr! n` instead of `congr! 1`\n* `convert_to ty at h` changes the type of the local hypothesis `h` to `ty`.\n  Any remaining `congr!` goals come first.\n\nOperating on the target, the tactic `convert_to ty using n`\nis the same as `convert (?_ : ty) using n`.\nThe difference is that `convert_to` takes a type but `convert` takes a proof term.\n\nExcept for it also being able to operate on local hypotheses,\nthe syntax for `convert_to` is the same as for `convert`, and it has variations such as\n`convert_to ← g` and `convert_to (config := {transparency := .default}) g`.\n\nNote that `convert_to ty at h` may leave a copy of `h` if a later local hypotheses or the target\ndepends on it, just like in `rw` or `simp`.\n\n# \"count_heartbeats\" [Mathlib.CountHeartbeats.tacticCount_heartbeats_](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Mathlib.CountHeartbeats.tacticCount_heartbeats_)\n\nCount the heartbeats used by a tactic, e.g.: `count_heartbeats simp`.\n\n# \"count_heartbeats!\" [Mathlib.CountHeartbeats.tacticCount_heartbeats!_In__](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Mathlib.CountHeartbeats.tacticCount_heartbeats!_In__)\n\n`count_heartbeats! in tac` runs a tactic 10 times, counting the heartbeats used, and logs the range\nand standard deviation. The tactic `count_heartbeats! n in tac` runs it `n` times instead.\n\n# \"dbg_trace\" [Parser.Tactic.dbgTrace](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Parser.Tactic.dbgTrace)\n\n`dbg_trace \"foo\"` prints `foo` when elaborated.\nUseful for debugging tactic control flow:\n```\nexample : False ∨ True := by\n  first\n  | apply Or.inl; trivial; dbg_trace \"left\"\n  | apply Or.inr; trivial; dbg_trace \"right\"\n```\n\n# \"decide\" [Parser.Tactic.decide](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Parser.Tactic.decide)\n\n`decide` attempts to prove the main goal (with target type `p`) by synthesizing an instance of `Decidable p`\nand then reducing that instance to evaluate the truth value of `p`.\nIf it reduces to `isTrue h`, then `h` is a proof of `p` that closes the goal.\n\nThe target is not allowed to contain local variables or metavariables.\nIf there are local variables, you can first try using the `revert` tactic with these local variables to move them into the target,\nor you can use the `+revert` option, described below.\n\nOptions:\n- `decide +revert` begins by reverting local variables that the target depends on,\n  after cleaning up the local context of irrelevant variables.\n  A variable is *relevant* if it appears in the target, if it appears in a relevant variable,\n  or if it is a proposition that refers to a relevant variable.\n- `decide +kernel` uses kernel for reduction instead of the elaborator.\n  It has two key properties: (1) since it uses the kernel, it ignores transparency and can unfold everything,\n  and (2) it reduces the `Decidable` instance only once instead of twice.\n- `decide +native` uses the native code compiler (`#eval`) to evaluate the `Decidable` instance,\n  admitting the result via the `Lean.ofReduceBool` axiom.\n  This can be significantly more efficient than using reduction, but it is at the cost of increasing the size\n  of the trusted code base.\n  Namely, it depends on the correctness of the Lean compiler and all definitions with an `@[implemented_by]` attribute.\n  Like with `+kernel`, the `Decidable` instance is evaluated only once.\n\nLimitation: In the default mode or `+kernel` mode, since `decide` uses reduction to evaluate the term,\n`Decidable` instances defined by well-founded recursion might not work because evaluating them requires reducing proofs.\nReduction can also get stuck on `Decidable` instances with `Eq.rec` terms.\nThese can appear in instances defined using tactics (such as `rw` and `simp`).\nTo avoid this, create such instances using definitions such as `decidable_of_iff` instead.\n\n## Examples\n\nProving inequalities:\n```lean\nexample : 2 + 2 ≠ 5 := by decide\n```\n\nTrying to prove a false proposition:\n```lean\nexample : 1 ≠ 1 := by decide\n/-\ntactic 'decide' proved that the proposition\n  1 ≠ 1\nis false\n-/\n```\n\nTrying to prove a proposition whose `Decidable` instance fails to reduce\n```lean\nopaque unknownProp : Prop\n\nopen scoped Classical in\nexample : unknownProp := by decide\n/-\ntactic 'decide' failed for proposition\n  unknownProp\nsince its 'Decidable' instance reduced to\n  Classical.choice ⋯\nrather than to the 'isTrue' constructor.\n-/\n```\n\n## Properties and relations\n\nFor equality goals for types with decidable equality, usually `rfl` can be used in place of `decide`.\n```lean\nexample : 1 + 1 = 2 := by decide\nexample : 1 + 1 = 2 := by rfl\n```\n\n# \"decreasing_tactic\" [tacticDecreasing_tactic](https://leanprover-community.github.io/mathlib4_docs/search.html?q=tacticDecreasing_tactic)\n\n`decreasing_tactic` is called by default on well-founded recursions in order\nto synthesize a proof that recursive calls decrease along the selected\nwell founded relation. It can be locally overridden by using `decreasing_by tac`\non the recursive definition, and it can also be globally extended by adding\nmore definitions for `decreasing_tactic` (or `decreasing_trivial`,\nwhich this tactic calls).\n\n# \"decreasing_trivial\" [tacticDecreasing_trivial](https://leanprover-community.github.io/mathlib4_docs/search.html?q=tacticDecreasing_trivial)\n\nExtensible helper tactic for `decreasing_tactic`. This handles the \"base case\"\nreasoning after applying lexicographic order lemmas.\nIt can be extended by adding more macro definitions, e.g.\n```\nmacro_rules | `(tactic| decreasing_trivial) =\u003e `(tactic| linarith)\n```\n\n# \"decreasing_trivial_pre_omega\" [tacticDecreasing_trivial_pre_omega](https://leanprover-community.github.io/mathlib4_docs/search.html?q=tacticDecreasing_trivial_pre_omega)\n\nVariant of `decreasing_trivial` that does not use `omega`, intended to be used in core modules\nbefore `omega` is available.\n\n# \"decreasing_with\" [tacticDecreasing_with_](https://leanprover-community.github.io/mathlib4_docs/search.html?q=tacticDecreasing_with_)\n\nConstructs a proof of decreasing along a well founded relation, by simplifying, then applying\nlexicographic order lemmas and finally using `ts` to solve the base case. If it fails,\nit prints a message to help the user diagnose an ill-founded recursive definition.\n\n# \"delta\" [Parser.Tactic.delta](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Parser.Tactic.delta)\n\n`delta id1 id2 ...` delta-expands the definitions `id1`, `id2`, ....\nThis is a low-level tactic, it will expose how recursive definitions have been\ncompiled by Lean.\n\n# \"discrete_cases\" [CategoryTheory.Discrete.tacticDiscrete_cases](https://leanprover-community.github.io/mathlib4_docs/search.html?q=CategoryTheory.Discrete.tacticDiscrete_cases)\n\nA simple tactic to run `cases` on any `Discrete α` hypotheses.\n\n# \"done\" [Parser.Tactic.done](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Parser.Tactic.done)\n\n`done` succeeds iff there are no remaining goals.\n\n# \"dsimp\" [Parser.Tactic.dsimp](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Parser.Tactic.dsimp)\n\nThe `dsimp` tactic is the definitional simplifier. It is similar to `simp` but only\napplies theorems that hold by reflexivity. Thus, the result is guaranteed to be\ndefinitionally equal to the input.\n\n# \"dsimp!\" [Parser.Tactic.dsimpAutoUnfold](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Parser.Tactic.dsimpAutoUnfold)\n\n`dsimp!` is shorthand for `dsimp` with `autoUnfold := true`.\nThis will rewrite with all equation lemmas, which can be used to\npartially evaluate many definitions.\n\n# \"dsimp?\" [Parser.Tactic.dsimpTrace](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Parser.Tactic.dsimpTrace)\n\n`simp?` takes the same arguments as `simp`, but reports an equivalent call to `simp only`\nthat would be sufficient to close the goal. This is useful for reducing the size of the simp\nset in a local invocation to speed up processing.\n```\nexample (x : Nat) : (if True then x + 2 else 3) = x + 2 := by\n  simp? -- prints \"Try this: simp only [ite_true]\"\n```\n\nThis command can also be used in `simp_all` and `dsimp`.\n\n# \"dsimp?!\" [Parser.Tactic.tacticDsimp?!_](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Parser.Tactic.tacticDsimp?!_)\n\n`simp?` takes the same arguments as `simp`, but reports an equivalent call to `simp only`\nthat would be sufficient to close the goal. This is useful for reducing the size of the simp\nset in a local invocation to speed up processing.\n```\nexample (x : Nat) : (if True then x + 2 else 3) = x + 2 := by\n  simp? -- prints \"Try this: simp only [ite_true]\"\n```\n\nThis command can also be used in `simp_all` and `dsimp`.\n\n# \"eapply\" [Batteries.Tactic.tacticEapply_](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Batteries.Tactic.tacticEapply_)\n\n`eapply e` is like `apply e` but it does not add subgoals for variables that appear\nin the types of other goals. Note that this can lead to a failure where there are\nno goals remaining but there are still metavariables in the term:\n```\nexample (h : ∀ x : Nat, x = x → True) : True := by\n  eapply h\n  rfl\n  -- no goals\n-- (kernel) declaration has metavariables '_example'\n```\n\n# \"econstructor\" [tacticEconstructor](https://leanprover-community.github.io/mathlib4_docs/search.html?q=tacticEconstructor)\n\n`econstructor` is like `constructor`\n(it calls `apply` using the first matching constructor of an inductive datatype)\nexcept only non-dependent premises are added as new goals.\n\n# \"elementwise\" [Elementwise.tacticElementwise___](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Elementwise.tacticElementwise___)\n\n\n# \"elementwise!\" [Elementwise.tacticElementwise!___](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Elementwise.tacticElementwise!___)\n\n\n# \"else\" [Parser.Tactic.tacDepIfThenElse](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Parser.Tactic.tacDepIfThenElse)\n\nIn tactic mode, `if h : t then tac1 else tac2` can be used as alternative syntax for:\n```\nby_cases h : t\n· tac1\n· tac2\n```\nIt performs case distinction on `h : t` or `h : ¬t` and `tac1` and `tac2` are the subproofs.\n\nYou can use `?_` or `_` for either subproof to delay the goal to after the tactic, but\nif a tactic sequence is provided for `tac1` or `tac2` then it will require the goal to be closed\nby the end of the block.\n\n# \"else\" [Parser.Tactic.tacIfThenElse](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Parser.Tactic.tacIfThenElse)\n\nIn tactic mode, `if t then tac1 else tac2` is alternative syntax for:\n```\nby_cases t\n· tac1\n· tac2\n```\nIt performs case distinction on `h† : t` or `h† : ¬t`, where `h†` is an anonymous\nhypothesis, and `tac1` and `tac2` are the subproofs. (It doesn't actually use\nnondependent `if`, since this wouldn't add anything to the context and hence would be\nuseless for proving theorems. To actually insert an `ite` application use\n`refine if t then ?_ else ?_`.)\n\n# \"eq_refl\" [Parser.Tactic.eqRefl](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Parser.Tactic.eqRefl)\n\n`eq_refl` is equivalent to `exact rfl`, but has a few optimizations.\n\n# \"erw\" [Parser.Tactic.tacticErw___](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Parser.Tactic.tacticErw___)\n\n`erw [rules]` is a shorthand for `rw (transparency := .default) [rules]`.\nThis does rewriting up to unfolding of regular definitions (by comparison to regular `rw`\nwhich only unfolds `@[reducible]` definitions).\n\n# \"eta_expand\" [Mathlib.Tactic.etaExpandStx](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Mathlib.Tactic.etaExpandStx)\n\n`eta_expand at loc` eta expands all sub-expressions at the given location.\nIt also beta reduces any applications of eta expanded terms, so it puts it\ninto an eta-expanded \"normal form.\"\nThis also exists as a `conv`-mode tactic.\n\nFor example, if `f` takes two arguments, then `f` becomes `fun x y =\u003e f x y`\nand `f x` becomes `fun y =\u003e f x y`.\n\nThis can be useful to turn, for example, a raw `HAdd.hAdd` into `fun x y =\u003e x + y`.\n\n# \"eta_reduce\" [Mathlib.Tactic.etaReduceStx](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Mathlib.Tactic.etaReduceStx)\n\n`eta_reduce at loc` eta reduces all sub-expressions at the given location.\nThis also exists as a `conv`-mode tactic.\n\nFor example, `fun x y =\u003e f x y` becomes `f` after eta reduction.\n\n# \"eta_struct\" [Mathlib.Tactic.etaStructStx](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Mathlib.Tactic.etaStructStx)\n\n`eta_struct at loc` transforms structure constructor applications such as `S.mk x.1 ... x.n`\n(pretty printed as, for example, `{a := x.a, b := x.b, ...}`) into `x`.\nThis also exists as a `conv`-mode tactic.\n\nThe transformation is known as eta reduction for structures, and it yields definitionally\nequal expressions.\n\nFor example, given `x : α × β`, then `(x.1, x.2)` becomes `x` after this transformation.\n\n# \"exact\" [Parser.Tactic.exact](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Parser.Tactic.exact)\n\n`exact e` closes the main goal if its target type matches that of `e`.\n\n# \"exact?\" [Parser.Tactic.exact?](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Parser.Tactic.exact?)\n\nSearches environment for definitions or theorems that can solve the goal using `exact`\nwith conditions resolved by `solve_by_elim`.\n\nThe optional `using` clause provides identifiers in the local context that must be\nused by `exact?` when closing the goal.  This is most useful if there are multiple\nways to resolve the goal, and one wants to guide which lemma is used.\n\n# \"exact_mod_cast\" [Parser.Tactic.tacticExact_mod_cast_](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Parser.Tactic.tacticExact_mod_cast_)\n\nNormalize casts in the goal and the given expression, then close the goal with `exact`.\n\n# \"exacts\" [Batteries.Tactic.exacts](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Batteries.Tactic.exacts)\n\nLike `exact`, but takes a list of terms and checks that all goals are discharged after the tactic.\n\n# \"exfalso\" [Parser.Tactic.tacticExfalso](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Parser.Tactic.tacticExfalso)\n\n`exfalso` converts a goal `⊢ tgt` into `⊢ False` by applying `False.elim`.\n\n# \"exists\" [Parser.Tactic.«tacticExists_,,»](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Parser.Tactic.«tacticExists_,,»)\n\n`exists e₁, e₂, ...` is shorthand for `refine ⟨e₁, e₂, ...⟩; try trivial`.\nIt is useful for existential goals.\n\n# \"existsi\" [Mathlib.Tactic.«tacticExistsi_,,»](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Mathlib.Tactic.«tacticExistsi_,,»)\n\n`existsi e₁, e₂, ⋯` applies the tactic `refine ⟨e₁, e₂, ⋯, ?_⟩`. It's purpose is to instantiate\nexistential quantifiers.\n\nExamples:\n\n```lean\nexample : ∃ x : Nat, x = x := by\n  existsi 42\n  rfl\n\nexample : ∃ x : Nat, ∃ y : Nat, x = y := by\n  existsi 42, 42\n  rfl\n```\n\n# \"ext\" [Ext.ext](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Ext.ext)\n\nApplies extensionality lemmas that are registered with the `@[ext]` attribute.\n* `ext pat*` applies extensionality theorems as much as possible,\n  using the patterns `pat*` to introduce the variables in extensionality theorems using `rintro`.\n  For example, the patterns are used to name the variables introduced by lemmas such as `funext`.\n* Without patterns,`ext` applies extensionality lemmas as much\n  as possible but introduces anonymous hypotheses whenever needed.\n* `ext pat* : n` applies ext theorems only up to depth `n`.\n\nThe `ext1 pat*` tactic is like `ext pat*` except that it only applies a single extensionality theorem.\n\nUnused patterns will generate warning.\nPatterns that don't match the variables will typically result in the introduction of anonymous hypotheses.\n\n# \"ext1\" [Ext.tacticExt1___](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Ext.tacticExt1___)\n\n`ext1 pat*` is like `ext pat*` except that it only applies a single extensionality theorem rather\nthan recursively applying as many extensionality theorems as possible.\n\nThe `pat*` patterns are processed using the `rintro` tactic.\nIf no patterns are supplied, then variables are introduced anonymously using the `intros` tactic.\n\n# \"extract_goal\" [Mathlib.Tactic.ExtractGoal.extractGoal](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Mathlib.Tactic.ExtractGoal.extractGoal)\n\n- `extract_goal` formats the current goal as a stand-alone theorem or definition after\n  cleaning up the local context of irrelevant variables.\n  A variable is *relevant* if (1) it occurs in the target type, (2) there is a relevant variable\n  that depends on it, or (3) the type of the variable is a proposition that depends on a\n  relevant variable.\n\n  If the target is `False`, then for convenience `extract_goal` includes all variables.\n- `extract_goal *` formats the current goal without cleaning up the local context.\n- `extract_goal a b c ...` formats the current goal after removing everything that the given\n  variables `a`, `b`, `c`, ... do not depend on.\n- `extract_goal ... using name` uses the name `name` for the theorem or definition rather than\n  the autogenerated name.\n\nThe tactic tries to produce an output that can be copy-pasted and just work,\nbut its success depends on whether the expressions are amenable\nto being unambiguously pretty printed.\n\nThe tactic responds to pretty printing options.\nFor example, `set_option pp.all true in extract_goal` gives the `pp.all` form.\n\n# \"extract_lets\" [Mathlib.extractLets](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Mathlib.extractLets)\n\nThe `extract_lets at h` tactic takes a local hypothesis of the form `h : let x := v; b`\nand introduces a new local definition `x := v` while changing `h` to be `h : b`.  It can be thought\nof as being a `cases` tactic for `let` expressions. It can also be thought of as being like\n`intros at h` for `let` expressions.\n\nFor example, if `h : let x := 1; x = x`, then `extract_lets x at h` introduces `x : Nat := 1` and\nchanges `h` to `h : x = x`.\n\nJust like `intros`, the `extract_lets` tactic either takes a list of names, in which case\nthat specifies the number of `let` bindings that must be extracted, or it takes no names, in which\ncase all the `let` bindings are extracted.\n\nThe tactic `extract_lets` (without `at`) or `extract_lets at h ⊢` acts as a weaker\nform of `intros` on the goal that only introduces obvious `let`s.\n\n# \"fail\" [Parser.Tactic.fail](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Parser.Tactic.fail)\n\n`fail msg` is a tactic that always fails, and produces an error using the given message.\n\n# \"fail_if_no_progress\" [Mathlib.Tactic.failIfNoProgress](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Mathlib.Tactic.failIfNoProgress)\n\n`fail_if_no_progress tacs` evaluates `tacs`, and fails if no progress is made on the main goal\nor the local context at reducible transparency.\n\n# \"fail_if_success\" [Parser.Tactic.failIfSuccess](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Parser.Tactic.failIfSuccess)\n\n`fail_if_success t` fails if the tactic `t` succeeds.\n\n# \"false_or_by_contra\" [Parser.Tactic.falseOrByContra](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Parser.Tactic.falseOrByContra)\n\nChanges the goal to `False`, retaining as much information as possible:\n\n* If the goal is `False`, do nothing.\n* If the goal is an implication or a function type, introduce the argument and restart.\n  (In particular, if the goal is `x ≠ y`, introduce `x = y`.)\n* Otherwise, for a propositional goal `P`, replace it with `¬ ¬ P`\n  (attempting to find a `Decidable` instance, but otherwise falling back to working classically)\n  and introduce `¬ P`.\n* For a non-propositional goal use `False.elim`.\n\n# \"fapply\" [Batteries.Tactic.tacticFapply_](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Batteries.Tactic.tacticFapply_)\n\n`fapply e` is like `apply e` but it adds goals in the order they appear,\nrather than putting the dependent goals first.\n\n# \"fconstructor\" [tacticFconstructor](https://leanprover-community.github.io/mathlib4_docs/search.html?q=tacticFconstructor)\n\n`fconstructor` is like `constructor`\n(it calls `apply` using the first matching constructor of an inductive datatype)\nexcept that it does not reorder goals.\n\n# \"field_simp\" [Mathlib.Tactic.FieldSimp.fieldSimp](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Mathlib.Tactic.FieldSimp.fieldSimp)\n\nThe goal of `field_simp` is to reduce an expression in a field to an expression of the form `n / d`\nwhere neither `n` nor `d` contains any division symbol, just using the simplifier (with a carefully\ncrafted simpset named `field_simps`) to reduce the number of division symbols whenever possible by\niterating the following steps:\n\n- write an inverse as a division\n- in any product, move the division to the right\n- if there are several divisions in a product, group them together at the end and write them as a\n  single division\n- reduce a sum to a common denominator\n\nIf the goal is an equality, this simpset will also clear the denominators, so that the proof\ncan normally be concluded by an application of `ring`.\n\n`field_simp [hx, hy]` is a short form for\n`simp (disch := field_simp_discharge) [-one_div, -one_divp, -mul_eq_zero, hx, hy, field_simps]`\n\nNote that this naive algorithm will not try to detect common factors in denominators to reduce the\ncomplexity of the resulting expression. Instead, it relies on the ability of `ring` to handle\ncomplicated expressions in the next step.\n\nAs always with the simplifier, reduction steps will only be applied if the preconditions of the\nlemmas can be checked. This means that proofs that denominators are nonzero should be included. The\nfact that a product is nonzero when all factors are, and that a power of a nonzero number is\nnonzero, are included in the simpset, but more complicated assertions (especially dealing with sums)\nshould be given explicitly. If your expression is not completely reduced by the simplifier\ninvocation, check the denominators of the resulting expression and provide proofs that they are\nnonzero to enable further progress.\n\nTo check that denominators are nonzero, `field_simp` will look for facts in the context, and\nwill try to apply `norm_num` to close numerical goals.\n\nThe invocation of `field_simp` removes the lemma `one_div` from the simpset, as this lemma\nworks against the algorithm explained above. It also removes\n`mul_eq_zero : x * y = 0 ↔ x = 0 ∨ y = 0`, as `norm_num` can not work on disjunctions to\nclose goals of the form `24 ≠ 0`, and replaces it with `mul_ne_zero : x ≠ 0 → y ≠ 0 → x * y ≠ 0`\ncreating two goals instead of a disjunction.\n\nFor example,\n```lean\nexample (a b c d x y : ℂ) (hx : x ≠ 0) (hy : y ≠ 0) :\n    a + b / x + c / x^2 + d / x^3 = a + x⁻¹ * (y * b / y + (d / x + c) / x) := by\n  field_simp\n  ring\n```\n\nMoreover, the `field_simp` tactic can also take care of inverses of units in\na general (commutative) monoid/ring and partial division `/ₚ`, see `Algebra.Group.Units`\nfor the definition. Analogue to the case above, the lemma `one_divp` is removed from the simpset\nas this works against the algorithm. If you have objects with an `IsUnit x` instance like\n`(x : R) (hx : IsUnit x)`, you should lift them with\n`lift x to Rˣ using id hx; rw [IsUnit.unit_of_val_units] clear hx`\nbefore using `field_simp`.\n\nSee also the `cancel_denoms` tactic, which tries to do a similar simplification for expressions\nthat have numerals in denominators.\nThe tactics are not related: `cancel_denoms` will only handle numeric denominators, and will try to\nentirely remove (numeric) division from the expression by multiplying by a factor.\n\n# \"field_simp_discharge\" [Mathlib.Tactic.FieldSimp.tacticField_simp_discharge](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Mathlib.Tactic.FieldSimp.tacticField_simp_discharge)\n\nDischarge strategy for the `field_simp` tactic.\n\n# \"filter_upwards\" [Mathlib.Tactic.filterUpwards](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Mathlib.Tactic.filterUpwards)\n\n`filter_upwards [h₁, ⋯, hₙ]` replaces a goal of the form `s ∈ f` and terms\n`h₁ : t₁ ∈ f, ⋯, hₙ : tₙ ∈ f` with `∀ x, x ∈ t₁ → ⋯ → x ∈ tₙ → x ∈ s`.\nThe list is an optional parameter, `[]` being its default value.\n\n`filter_upwards [h₁, ⋯, hₙ] with a₁ a₂ ⋯ aₖ` is a short form for\n`{ filter_upwards [h₁, ⋯, hₙ], intros a₁ a₂ ⋯ aₖ }`.\n\n`filter_upwards [h₁, ⋯, hₙ] using e` is a short form for\n`{ filter_upwards [h1, ⋯, hn], exact e }`.\n\nCombining both shortcuts is done by writing `filter_upwards [h₁, ⋯, hₙ] with a₁ a₂ ⋯ aₖ using e`.\nNote that in this case, the `aᵢ` terms can be used in `e`.\n\n# \"fin_cases\" [finCases](https://leanprover-community.github.io/mathlib4_docs/search.html?q=finCases)\n\n`fin_cases h` performs case analysis on a hypothesis of the form\n`h : A`, where `[Fintype A]` is available, or\n`h : a ∈ A`, where `A : Finset X`, `A : Multiset X` or `A : List X`.\n\nAs an example, in\n```\nexample (f : ℕ → Prop) (p : Fin 3) (h0 : f 0) (h1 : f 1) (h2 : f 2) : f p.val := by\n  fin_cases p; simp\n  all_goals assumption\n```\nafter `fin_cases p; simp`, there are three goals, `f 0`, `f 1`, and `f 2`.\n\n# \"fin_omega\" [Fin.tacticFin_omega](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Fin.tacticFin_omega)\n\nPreprocessor for `omega` to handle inequalities in `Fin`.\nNote that this involves a lot of case splitting, so may be slow.\n\n# \"find\" [Mathlib.Tactic.Find.tacticFind](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Mathlib.Tactic.Find.tacticFind)\n\n\n# \"finiteness\" [finiteness](https://leanprover-community.github.io/mathlib4_docs/search.html?q=finiteness)\n\nTactic to solve goals of the form `*** \u003c ∞` and (equivalently) `*** ≠ ∞` in the extended\nnonnegative reals (`ℝ≥0∞`).\n\n# \"finiteness?\" [finiteness?](https://leanprover-community.github.io/mathlib4_docs/search.html?q=finiteness?)\n\nTactic to solve goals of the form `*** \u003c ∞` and (equivalently) `*** ≠ ∞` in the extended\nnonnegative reals (`ℝ≥0∞`).\n\n# \"finiteness_nonterminal\" [finiteness_nonterminal](https://leanprover-community.github.io/mathlib4_docs/search.html?q=finiteness_nonterminal)\n\nTactic to solve goals of the form `*** \u003c ∞` and (equivalently) `*** ≠ ∞` in the extended\nnonnegative reals (`ℝ≥0∞`).\n\n# \"first\" [Parser.Tactic.first](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Parser.Tactic.first)\n\n`first | tac | ...` runs each `tac` until one succeeds, or else fails.\n\n# \"focus\" [Parser.Tactic.focus](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Parser.Tactic.focus)\n\n`focus tac` focuses on the main goal, suppressing all other goals, and runs `tac` on it.\nUsually `· tac`, which enforces that the goal is closed by `tac`, should be preferred.\n\n# \"forward\" [Aesop.Frontend.tacticForward___](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Aesop.Frontend.tacticForward___)\n\n\n# \"forward?\" [Aesop.Frontend.tacticForward?___](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Aesop.Frontend.tacticForward?___)\n\n\n# \"frac_tac\" [RatFunc.tacticFrac_tac](https://leanprover-community.github.io/mathlib4_docs/search.html?q=RatFunc.tacticFrac_tac)\n\nSolve equations for `RatFunc K` by working in `FractionRing K[X]`.\n\n# \"fun_prop\" [Mathlib.Meta.FunProp.funPropTacStx](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Mathlib.Meta.FunProp.funPropTacStx)\n\nTactic to prove function properties\n\n# \"funext\" [tacticFunext___](https://leanprover-community.github.io/mathlib4_docs/search.html?q=tacticFunext___)\n\nApply function extensionality and introduce new hypotheses.\nThe tactic `funext` will keep applying the `funext` lemma until the goal target is not reducible to\n```\n  |-  ((fun x =\u003e ...) = (fun x =\u003e ...))\n```\nThe variant `funext h₁ ... hₙ` applies `funext` `n` times, and uses the given identifiers to name the new hypotheses.\nPatterns can be used like in the `intro` tactic. Example, given a goal\n```\n  |-  ((fun x : Nat × Bool =\u003e ...) = (fun x =\u003e ...))\n```\n`funext (a, b)` applies `funext` once and performs pattern matching on the newly introduced pair.\n\n# \"gcongr\" [Mathlib.Tactic.GCongr.tacticGcongr__With__](https://leanprover-community.github.io/mathlib4_docs/search.html?q=Mathlib.Tactic.GCongr.tacticGcongr__With__)\n\nThe `gcongr` tactic applies \"generalized congruence\" rules, reducing a relational goal\nbetween a LHS and RHS matching the same pattern to relational subgoals between the differing\ninputs to the pattern.  For example,\n```\nexample {a b x c d : ℝ} (h1 : a + 1 ≤ b + 1) (h2 : c + 2 ≤ d + 2) :\n    x ^ 2 * a + c ≤ x ^ 2 * b + d := by\n  gcongr\n  · linarith\n  · linarith\n```\nThis example has the goal of proving the relation `≤` between a LHS and RHS both of the pattern\n```\nx ^ 2","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftristan-f-r%2Fmathlib4-tactics","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftristan-f-r%2Fmathlib4-tactics","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftristan-f-r%2Fmathlib4-tactics/lists"}