Zulip Chat Archive
Stream: general
Topic: more expr munging
Scott Morrison (Sep 09 2018 at 11:28):
Say I have an expr
representing an iterated pi
type, which is finally an equation, something like Π (a : ℕ) (b : ℕ), f a b = g (a + b)
. From that, I want to produce f ?m_1 ?m_2
, where ?m_1
and ?m_2
are newly created metavariables of the appropriate types.
Scott Morrison (Sep 09 2018 at 11:28):
Any suggestions?
Reid Barton (Sep 09 2018 at 11:31):
Are you guaranteed that the left hand side will be literally <something> a b
, where a
and b
are the variables introduced by the Pis in order? Or could it be some arbitrary expression involving a
and b
?
Simon Hudon (Sep 09 2018 at 11:34):
meta def get_lhs : expr -> tactic expr | (expr.pi n bi d b) := do v <- mk_local' n bi d, b' <- whnf $ b.instantiate_var v get_lhs b' | `(%%a = %%b) := pure a | _ := failed
Reid Barton (Sep 09 2018 at 11:36):
Yes this strategy is what I was about to suggest. Peel off one outer Pi at a type, leaving a formula with a free variable, and then substitute a fresh metavariable or whatever else you want for that free variable
Simon Hudon (Sep 09 2018 at 11:37):
Actually, we can be more direct:
meta def get_lhs : expr -> tactic expr | (expr.pi n bi d b) := do v <- mk_meta_var d, b' <- whnf $ b.instantiate_var v get_lhs b' | `(%%a = %%b) := pure a | _ := failed
Scott Morrison (Sep 09 2018 at 11:37):
(I'm doubly impressed, Simon, that your code often doesn't quite compile: there's a comma missing in that first one. :-)
Simon Hudon (Sep 09 2018 at 11:38):
Where would be the fun if you didn't have to fix my mistakes?
Scott Morrison (Sep 09 2018 at 11:48):
So I'm trying to do something a bit fancier here, and while get_lhs
work as requested, really I want something more. :-)
Simon Hudon (Sep 09 2018 at 11:49):
I'm listening (sort of)
Scott Morrison (Sep 09 2018 at 11:50):
I had written:
meta def substitutions' : expr → bool → list expr → tactic (tactic (expr × expr × list expr)) | (expr.pi n bi d b) symm types := do substitutions' b symm (d :: types) | `(%%lhs = %%rhs) symm types := do let (lhs, rhs) := if symm then (rhs, lhs) else (lhs, rhs), let tac := (do mvars ← types.mmap mk_meta_var, let pattern := lhs.instantiate_vars mvars, ty ← infer_type pattern, return (pattern, ty, mvars)), return tac | _ _ _ := failed
Scott Morrison (Sep 09 2018 at 11:51):
The idea being to return a tactic, which could be invoked multiple times, each time producing the pattern with "fresh" mvars.
Scott Morrison (Sep 09 2018 at 11:51):
However it's ... still somewhat mysteriously ... not working in all cases. (Sorry this is far from a MWE.)
Reid Barton (Sep 09 2018 at 11:53):
Is this supposed to be more efficient than just invoking something like get_lhs
repeatedly?
Scott Morrison (Sep 09 2018 at 11:54):
Yeah, I guess so.
Scott Morrison (Sep 09 2018 at 11:54):
But maybe I am needlessly complicating things. :-(
Simon Hudon (Sep 09 2018 at 11:55):
I think you need to reverse
mvars
Reid Barton (Sep 09 2018 at 11:56):
It's probably about equally or less efficient because the representation of that tactic
object in the VM is going to be basically the same as or a more complicated structure than the outer Pis of the original type.
Scott Morrison (Sep 09 2018 at 11:59):
Hmm. I had tried (on a purely voodoo basis) reversing mvars
, without apparent success. Let me go away on de-complicate for a bit. :-)
Scott Morrison (Sep 09 2018 at 11:59):
Thanks for the help!
Simon Hudon (Sep 09 2018 at 11:59):
After squinting at it for a while, I agree with @Reid Barton
Reid Barton (Sep 09 2018 at 12:02):
(Or at least, that would be true in the GHC runtime system, which is probably a terrible mental model for the Lean VM but the best one I have available.)
Simon Hudon (Sep 09 2018 at 12:04):
My reasoning is that, for each bound variable, the expensive thing is instantiate_var
, the number of which does not decrease in this approach
Reid Barton (Sep 09 2018 at 12:05):
Right, you only save the decomposition of the Pis.
Reid Barton (Sep 09 2018 at 12:08):
Which is cheap anyways, but to make things worse, you replace it by having to do an equal number of applications-of-variable-functions (the inner tactic
which you build up).
Reid Barton (Sep 09 2018 at 12:11):
Oh wait, you implemented it in a way so that there is only one closure being built (tac
), but still each invocation of tac
has to process the list types
, which has the same information as the outer Pis of the original expression.
Scott Morrison (Sep 09 2018 at 12:13):
and, happily it all seems to work now!
Scott Morrison (Sep 09 2018 at 12:13):
(or at least the "all" that I hoped to have done tonight!)
Last updated: Dec 20 2023 at 11:08 UTC