File: Mathlib/Tactic/ApplyFun.lean

full_name: Mathlib.Tactic.initFn._@.Mathlib.Tactic.ApplyFun._hyg.6
code: initialize registerTraceClass `apply_fun
goal: IO Unit

full_name: Mathlib.Tactic.applyFunHyp
code: /-- Apply a function to a hypothesis. -/
def applyFunHyp (f : Term) (using? : Option Term) (h : FVarId) (g : MVarId) :
    TacticM (List MVarId) 
goal: Lean.Elab.Tactic.TacticM (List Lean.MVarId)

full_name: Mathlib.Tactic.applyFunTargetFailure
code: /-- Failure message for `applyFunTarget`. -/
def applyFunTargetFailure (f : Term) : MetaM (List MVarId) 
goal: Lean.MetaM (List Lean.MVarId)

full_name: Mathlib.Tactic.maybeProveInjective
code: /-- Given a metavariable `ginj` of type `Injective f`, try to prove it.
Returns whether it was successful. -/
def maybeProveInjective (ginj : Expr) (using? : Option Expr) : MetaM Bool 
goal: Lean.MetaM Bool

full_name: Mathlib.Tactic.applyFunTarget
code: /-- Apply a function to the main goal. -/
def applyFunTarget (f : Term) (using? : Option Term) (g : MVarId) : TacticM (List MVarId) 
goal: Lean.Elab.Tactic.TacticM (List Lean.MVarId)

full_name: Mathlib.Tactic.applyFun
code: /--
Apply a function to an equality or inequality in either a local hypothesis or the goal.

* If we have `h : a = b`, then `apply_fun f at h` will replace this with `h : f a = f b`.
* If we have `h : a ≤ b`, then `apply_fun f at h` will replace this with `h : f a ≤ f b`,
  and create a subsidiary goal `Monotone f`.
  `apply_fun` will automatically attempt to discharge this subsidiary goal using `mono`,
  or an explicit solution can be provided with `apply_fun f at h using P`, where `P : Monotone f`.
* If we have `h : a < b`, then `apply_fun f at h` will replace this with `h : f a < f b`,
  and create a subsidiary goal `StrictMono f` and behaves as in the previous case.
* If we have `h : a ≠ b`, then `apply_fun f at h` will replace this with `h : f a ≠ f b`,
  and create a subsidiary goal `Injective f` and behaves as in the previous two cases.
* If the goal is `a ≠ b`, `apply_fun f` will replace this with `f a ≠ f b`.
* If the goal is `a = b`, `apply_fun f` will replace this with `f a = f b`,
  and create a subsidiary goal `injective f`.
  `apply_fun` will automatically attempt to discharge this subsidiary goal using local hypotheses,
  or if `f` is actually an `Equiv`,
  or an explicit solution can be provided with `apply_fun f using P`, where `P : Injective f`.
* If the goal is `a ≤ b` (or similarly for `a < b`), and `f` is actually an `OrderIso`,
  `apply_fun f` will replace the goal with `f a ≤ f b`.
  If `f` is anything else (e.g. just a function, or an `Equiv`), `apply_fun` will fail.


Typical usage is:
```lean
open Function

example (X Y Z : Type) (f : X → Y) (g : Y → Z) (H : Injective <| g ∘ f) :
    Injective f := by
  intros x x' h
  apply_fun g at h
  exact H h
```

The function `f` is handled similarly to how it would be handled by `refine` in that `f` can contain
placeholders. Named placeholders (like `?a` or `?_`) will produce new goals.
 -/
syntax (name := applyFun) "apply_fun " term (location)? (" using " term)? : tactic
goal: Lean.ParserDescr

full_name: Mathlib.Tactic._aux_Mathlib_Tactic_ApplyFun___elabRules_Mathlib_Tactic_applyFun_1
code: elab_rules : tactic | `(tactic| apply_fun $f $[$loc]? $[using $P]?) => do
  withLocation (expandOptLocation (Lean.mkOptionalNode loc))
    (atLocal := fun h ↦ do replaceMainGoal <| ← applyFunHyp f P h (← getMainGoal))
    (atTarget := withMainContext do
      replaceMainGoal <| ← applyFunTarget f P (← getMainGoal))
    (failed := fun _ ↦ throwError "apply_fun failed")
goal: Lean.Elab.Tactic.Tactic