File: .lake/packages/lean4/src/lean/Lean/Meta/Match/MatcherApp/Transform.lean

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Meta.Match.MatcherApp.Transform.0.Lean.Meta.MatcherApp.updateAlts
code: /-- Auxiliary function for MatcherApp.addArg -/
private partial def updateAlts (unrefinedArgType : Expr) (typeNew : Expr) (altNumParams : Array Nat) (alts : Array Expr) (refined : Bool) (i : Nat) : MetaM (Array Nat × Array Expr) 
goal: Lean.MetaM (Array Nat × Array Lean.Expr)

full_name: Lean.Meta.MatcherApp.addArg
code: /-- Given
  - matcherApp `match_i As (fun xs => motive[xs]) discrs (fun ys_1 => (alt_1 : motive (C_1[ys_1])) ... (fun ys_n => (alt_n : motive (C_n[ys_n]) remaining`, and
  - expression `e : B[discrs]`,
  Construct the term
  `match_i As (fun xs => B[xs] -> motive[xs]) discrs (fun ys_1 (y : B[C_1[ys_1]]) => alt_1) ... (fun ys_n (y : B[C_n[ys_n]]) => alt_n) e remaining`.

  We use `kabstract` to abstract the discriminants from `B[discrs]`.

  This method assumes
  - the `matcherApp.motive` is a lambda abstraction where `xs.size == discrs.size`
  - each alternative is a lambda abstraction where `ys_i.size == matcherApp.altNumParams[i]`

  This is used in in `Lean.Elab.PreDefinition.WF.Fix` when replacing recursive calls with calls to
  the argument provided by `fix` to refine the termination argument, which may mention `major`.
  See there for how to use this function.
-/
def addArg (matcherApp : MatcherApp) (e : Expr) : MetaM MatcherApp 
goal: Lean.MetaM Lean.Meta.MatcherApp

full_name: Lean.Meta.MatcherApp.addArg?
code: /-- Similar to `MatcherApp.addArg`, but returns `none` on failure. -/
def addArg? (matcherApp : MatcherApp) (e : Expr) : MetaM (Option MatcherApp) 
goal: Lean.MetaM (Option Lean.Meta.MatcherApp)

full_name: Lean.Meta.MatcherApp.refineThrough
code: /-- Given
  - matcherApp `match_i As (fun xs => motive[xs]) discrs (fun ys_1 => (alt_1 : motive (C_1[ys_1])) ... (fun ys_n => (alt_n : motive (C_n[ys_n]) remaining`, and
  - a expression `B[discrs]` (which may not be a type, e.g. `n : Nat`),
  returns the expressions `fun ys_1 ... ys_i => B[C_1[ys_1]] ... B[C_n[ys_n]]`,

  This method assumes
  - the `matcherApp.motive` is a lambda abstraction where `xs.size == discrs.size`
  - each alternative is a lambda abstraction where `ys_i.size == matcherApp.altNumParams[i]`

  This is similar to `MatcherApp.addArg` when you only have an expression to
  refined, and not a type with a value.

  This is used in in `Lean.Elab.PreDefinition.WF.GuessFix` when constructing the context of recursive
  calls to refine the functions' paramter, which may mention `major`.
  See there for how to use this function.
-/
def refineThrough (matcherApp : MatcherApp) (e : Expr) : MetaM (Array Expr) 
goal: Lean.MetaM (Array Lean.Expr)

full_name: Lean.Meta.MatcherApp.refineThrough?
code: /-- A non-failing version of `MatcherApp.refineThrough` -/
def refineThrough? (matcherApp : MatcherApp) (e : Expr) :
    MetaM (Option (Array Expr)) 
goal: Lean.MetaM (Option (Array Lean.Expr))

full_name: Lean.Meta.MatcherApp.arrowDomainsN
code: /--
Given `n` and a non-dependent function type `α₁ → α₂ → ... → αₙ → Sort u`, returns the
types `α₁, α₂, ..., αₙ`. Throws an error if there are not at least `n` argument types or if a
later argument type depends on a prior one (i.e., it's a dependent function type).

This can be used to infer the expected type of the alternatives when constructing a `MatcherApp`.
-/
-- TODO: Which is the natural module for this?
def arrowDomainsN (n : Nat) (type : Expr) : MetaM (Array Expr) 
goal: Lean.MetaM (Array Lean.Expr)

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Meta.Match.MatcherApp.Transform.0.Lean.Meta.MatcherApp.withUserNamesImpl
code: private def withUserNamesImpl {α} (fvars : Array Expr) (names : Array Name) (k : MetaM α) : MetaM α 
goal: Lean.MetaM α

full_name: Lean.Meta.MatcherApp.withUserNames
code: /--
Sets the user name of the FVars in the local context according to the given array of names.

If they differ in size the shorter size wins.
-/
def withUserNames {n} [MonadControlT MetaM n] [Monad n]
  {α} (fvars : Array Expr) (names : Array Name) (k : n α) : n α 
goal: n α

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Meta.Match.MatcherApp.Transform.0.Lean.Meta.MatcherApp.forallAltTelescope'
code: private def forallAltTelescope'
    {n} [Monad n] [MonadControlT MetaM n]
    {α} (origAltType : Expr) (numParams numDiscrEqs : Nat)
    (k : Array Expr → Array Expr → n α) : n α 
goal: n α

full_name: Lean.Meta.MatcherApp.transform
code: /--
Performs a possibly type-changing transformation to a `MatcherApp`.

* `onParams` is run on each parameter and discriminant
* `onMotive` runs on the body of the motive, and is passed the motive parameters
  (one for each `MatcherApp.discrs`)
* `onAlt` runs on each alternative, and is passed the expected type of the alternative,
   as inferred from the motive
* `onRemaining` runs on the remaining arguments (and may change their number)

If `useSplitter` is true, the matcher is replaced with the splitter.
NB: Not all operations on `MatcherApp` can handle one `matcherName` is a splitter.

The array `addEqualities`, if provided, indicates for which of the discriminants an equality
connecting the discriminant to the parameters of the alternative (like in `match h : x with …`)
should be added (if it is isn't already there).

This function works even if the the type of alternatives do *not* fit the inferred type. This
allows you to post-process the `MatcherApp` with `MatcherApp.inferMatchType`, which will
infer a type, given all the alternatives.
-/
def transform
    {n} [MonadLiftT MetaM n] [MonadControlT MetaM n] [Monad n] [MonadError n] [MonadEnv n] [MonadLog n]
    [AddMessageContext n] [MonadOptions n]
    (matcherApp : MatcherApp)
    (useSplitter := false)
    (addEqualities : Array Bool := mkArray matcherApp.discrs.size false)
    (onParams : Expr → n Expr := pure)
    (onMotive : Array Expr → Expr → n Expr := fun _ e => pure e)
    (onAlt : Expr → Expr → n Expr := fun _ e => pure e)
    (onRemaining : Array Expr → n (Array Expr) := pure) :
    n MatcherApp 
goal: n Lean.Meta.MatcherApp

full_name: Lean.Meta.MatcherApp.inferMatchType
code: /--
Given a `MatcherApp`, replaces the motive with one that is inferred from the actual types of the
alternatives.

For example, given
```
(match (motive := Nat → Unit → ?) n with
 0 => 1
 _ => true) ()
```
(for any `?`; the motive’s result type be ignored) will give this type
```
(match n with
 | 0 => Nat
 | _ => Bool)
```

The given `MatcherApp` must not use a splitter in `matcherName`.
The resulting expression *will* use the splitter corresponding to `matcherName` (this is necessary
for the construction).

Interally, this needs to reduce the matcher in a given branch; this is done using
`Split.simpMatchTarget`.
-/
def inferMatchType (matcherApp : MatcherApp) : MetaM MatcherApp 
goal: Lean.MetaM Lean.Meta.MatcherApp