Zulip Chat Archive

Stream: lean4

Topic: elab a term within a tactic


Thomas Murrills (Nov 11 2022 at 19:29):

This might be a basic question, but let's say I want to define a term elaboration meant to be used within a tactic (in such a way that it depends on the current goals). Is that possible?

I get a type mismatch error when I try to use Tactic.getMainDeclwithin a term elaboration, and a different one if I try to return an Expr within a tactic elab. (Can monad lifting can help out here somehow? Or do I need a different type of elaboration?)

Jannis Limperg (Nov 11 2022 at 19:46):

MetaM lifts into TermElabM lifts into TacticM. To use a TermElabM computation which depends on the current goals, you'll have to use getGoals first and pass this to the TermElabM computation (which gets auto-lifted into TacticM). To lift a MetaM tactic into TacticM, use liftMetaTactic. Does that help?

Thomas Murrills (Nov 11 2022 at 19:56):

Just to make sure we're on the same page, getGoals has type TacticM (List MVarId), right? If I try to use this within the TermElabM computation, e.g. let goals ← Tactic.getGoals, I get hit with a type mismatch, saying that it should have type TermElabM .... To pass the result to the TermElabM computation, we'd have to be in a TacticM computation "on the outside", right? My problem then is being able to return an expression from the TacticM computation, since it seems like that's fundamentally not what TacticM Unit can do. Unless...is there a way to define a TacticM Expr elaboration somehow?

Sebastian Ullrich (Nov 11 2022 at 20:08):

Terms and tactics are distinct. A term elaborator cannot depend on the current goal.

Mario Carneiro (Nov 11 2022 at 20:23):

This cannot be done, and moreover it is a really weird thing to do. The closest approximation would be a tactic with a term argument, which uses a side channel to pass its list of goals to a subterm of the input argument. (squeeze_scope has to do something like this because it passes information about the scope to all nested simp calls.)

Mario Carneiro (Nov 11 2022 at 20:23):

I think it might help to explain what you want to do (#xy)

Thomas Murrills (Nov 11 2022 at 20:34):

So, the actual application was just to see if I could "improve on" have_field and, instead of having it have things into the context, be able to simply use something like currentFieldProj in syntax to represent the projection itself. Currently, this would have to read off some metadata from the current goal. (I do wonder if there's a better way to do this, though—something in the environment, maybe?)

I was mostly just trying to see if I could do it for fun/learning/experience—as far as I can tell, have_field isn't used once in mathlib3 :upside_down: (in contrast to refine_struct, which is used occasionally.) Not spending too much time on it, though, since there are other, more useful things to be done... :)


Last updated: Dec 20 2023 at 11:08 UTC