Zulip Chat Archive
Stream: metaprogramming / tactics
Topic: List of projections of structure
Eric Wieser (Jul 09 2022 at 16:15):
What's the easiest way to fill this sorry:
def get_projections (t : expr) : list expr := sorry
such that get_projections `(prod X Y) = [`(@prod.fst X Y), `(@prod.snd X Y)]
Floris van Doorn (Jul 10 2022 at 09:24):
You can use docs#environment.structure_fields to the (name of the) head of the expression, and then apply each of them to the same arguments as the original expression. You'd have to wrap it inside a tactic though.
Floris van Doorn (Jul 10 2022 at 09:31):
import tactic.core
open tactic
meta def get_projections (t : expr) : tactic (list expr) := do
env ← get_env,
let str_nm := t.get_app_fn.const_name,
proj_nms ← env.structure_fields_full str_nm,
let univs := t.get_app_fn.univ_levels,
let args := t.get_app_args,
let projs := proj_nms.map (λ proj_nm, (expr.const proj_nm univs).mk_app args),
return projs
#eval get_projections `(bool × nat) >>= trace -- [prod.fst, prod.snd]
#eval get_projections `(bool × nat) >>= (λ x, trace $ x.map expr.to_raw_fmt)
#eval get_projections `(bool × nat) >>= (λ x, x.mmap infer_type >>= trace) -- [bool × ℕ → bool, bool × ℕ → ℕ]
(not extensively tested)
You might want to apply instantiate_mvars
and whnf
tot
first, in case t
is not exactly in the right form.
EDIT: fixed bug
Eric Wieser (Jul 12 2022 at 12:49):
In #15207 I ended up with
/-- ``(s_name, (c_name, c_fun), [(p_name, p_fun), ...]) ← get_constructor_and_projections `(struct n)``
gets the names and partial invocations of the constructor and projections of a structure -/
meta def get_constructor_and_projections (t : expr) :
tactic (name × (name × expr) × list (name × expr)):=
do
(const I ls, args) ← pure (get_app_fn_args t),
env ← get_env,
[ctor] ← pure (env.constructors_of I),
ctor ← do
{ d ← get_decl ctor,
let a := @expr.const tt ctor $ d.univ_params.map level.param,
pure (ctor, a.mk_app args) },
ctor_type ← infer_type ctor.2,
tt ← pure ctor_type.is_pi | pure (I, ctor, []),
some fields ← pure (env.structure_fields I) | fail!"Not a structure",
projs ← fields.mmap $ λ f, do
{ d ← get_decl (I ++ f),
let a := @expr.const tt (I ++ f) $ d.univ_params.map level.param,
pure (f, a.mk_app args) },
pure (I, ctor, projs)
Yury G. Kudryashov (Jul 12 2022 at 13:15):
What do you want to get in case of docs#monoid? Should it include to_semigroup
?
Eric Wieser (Jul 12 2022 at 13:52):
Good question, I think for my use-case I don't really care that much
Last updated: Dec 20 2023 at 11:08 UTC