Zulip Chat Archive

Stream: mathlib4

Topic: Alternative MetaM


Scott Morrison (Aug 23 2021 at 05:11):

failed to synthesize instance
  Alternative MetaM

Am I expecting the wrong thing here?

I've been implementing solve_by_elim in Lean4, and I have a very hacky solution with mutable variables inside try ... catch blocks in order to test if a tactic is failing, but the "obvious" approach using List.firstM or similar fails with the error above.

Scott Morrison (Aug 23 2021 at 05:30):

Providing a #mwe:

import Lean.Meta.Tactic.Apply
import Lean.Elab.Tactic.Basic

open Lean.Elab.Tactic

/-- Attempt to solve the given metavariable by repeating applying a local hypothesis. -/
def Lean.Meta.solveByElim : Nat  MVarId  MetaM Unit
  | 0, mvarId => throwError "fail"
  | (n+1), mvarId => do
    -- We attempt to find a local declaration which can be applied,
    -- and for which all resulting sub-goals can be discharged using `solveByElim n`.
    let r  ( getLCtx).findDeclRevM? fun localDecl => do
      if localDecl.isAuxDecl then
        return none
      else
        let mut success := false
        let s  try
          for g in ( apply mvarId localDecl.toExpr) do solveByElim n g
          success := true
        catch | _ => success := false
         if success then some Unit.unit else none

namespace Lean.Elab
namespace Tactic

elab "solveByElim" : tactic => withMainContext do
  Meta.solveByElim 6 ( getMainGoal)

end Tactic
end Lean.Elab

def test1 (h : Nat) : Nat := by solveByElim
def test2 {α β : Type} (f : α  β) (a : α) : β := by solveByElim
def test3 {α β : Type} (f : α  α  β) (a : α) : β := by solveByElim
def test4 {α β γ : Type} (f : α  β) (g : β  γ) (a : α) : γ := by solveByElim
def test5 {α β γ : Type} (f : α  β) (g : β  γ) (b : β) : γ := by solveByElim

demonstrates the bare bones of solveByElim, but the success variable is obviously all boilerplate.

I'd hoped I could just write

import Lean.Meta.Tactic.Apply
import Lean.Elab.Tactic.Basic

namespace Lean.LocalContext

universe u v
variable {m : Type u  Type v} [Monad m] [Alternative m]
variable {β : Type u}

/-- Return the result of `f` on the first local declaration on which `f` succeeds. -/
def firstDeclM (lctx : LocalContext) (f : LocalDecl  m β) : m β :=
  do match ( lctx.findDeclM? (optional  f)) with
  | none   => failure
  | some b => b

end Lean.LocalContext

open Lean.Elab.Tactic

/-- Attempt to solve the given metavariable by repeating applying a local hypothesis. -/
def Lean.Meta.solveByElim : Nat  MVarId  MetaM Unit
  | 0, mvarId => throwError "fail"
  | (n+1), mvarId => do
    -- We attempt to find a local declaration which can be applied,
    -- and for which all resulting sub-goals can be discharged using `solveByElim n`.
       ( getLCtx).firstDeclM fun localDecl => do
         if localDecl.isAuxDecl then
           failure
         else
           for g in ( apply mvarId localDecl.toExpr) do solveByElim n g

instead, but this fails trying to synthesize Alternative MetaM.

Recommendations for a concise solution welcome! :-)

Leonardo de Moura (Aug 23 2021 at 05:30):

Added https://github.com/leanprover/lean4/commit/5a7044365b70a434d59d34f0d302c88ce83f9715


Last updated: Dec 20 2023 at 11:08 UTC