Zulip Chat Archive
Stream: general
Topic: Documentation about tactic for default value in a structure
Andrej Bauer (Nov 10 2021 at 10:05):
Where can I read about the meaning of . obviously
in
structure simple_graph (V : Type u) :=
(adj : V → V → Prop)
(sym : symmetric adj . obviously)
(loopless : irreflexive adj . obviously)
My guess is that it means "use the tactic obviously
to construct a value if none given". What I am looking for is a way to construct such simple graphs, but I want to provide my custom tactics for the fields sym
and loopless
. (Or even better, convince the type class mechanism to unfold symmetric
and irreflexive
, as that would allow me to provide proof terms directly.)
Scott Morrison (Nov 10 2021 at 10:07):
You can put any tactic you like after the .
. It just has to have type tactic unit
, so sometime you need to make an auxiliary definition to wrap a tactic with a more complicated type.
Scott Morrison (Nov 10 2021 at 10:07):
e.g. meta def my_foo : tactic unit := `[foo]
usually suffices to wrap an interactive tactic as a tactic unit
.
Andrej Bauer (Nov 10 2021 at 10:07):
But I cannot change the definition of simple_graph
in the standard library.
Scott Morrison (Nov 10 2021 at 10:08):
Ah!
Scott Morrison (Nov 10 2021 at 10:08):
Actually, obviously
is an overridable tactic!
Scott Morrison (Nov 10 2021 at 10:08):
(Although we never really made use of this; it has constant meaning throughout mathlib.)
Andrej Bauer (Nov 10 2021 at 10:08):
I have a proof term that would work, if only symmetric
and irreflexive
were @[reducible]
(I think), which they are not.
Andrej Bauer (Nov 10 2021 at 10:09):
It sounds like "overriding tactics" is the sort of thing that leads to a shotgun hole in the knee.
Scott Morrison (Nov 10 2021 at 10:09):
Yes. It was a bad idea, but it is still there to shoot yourself in the knee if you want to. :-)
Scott Morrison (Nov 10 2021 at 10:10):
It seems you just write
@[obviously] meta def my_obviously : tactic unit := ...
and from then on it has a new meaning.
Scott Morrison (Nov 10 2021 at 10:11):
You can just write a wrapper that uses your alternative tactics, I guess.
Andrej Bauer (Nov 10 2021 at 10:13):
To explain what I am after, it's a convenient way to generate simple graphs like this:
def my_adj := ....
example: simple_graph (fin 4) :=
{ adj := my_adj,
sym := begin unfold symmetric, exact cow rfl end,
loopless := begin unfold irreflexive, exact cow rfl end
}
So I either have to get rid of the unfold
and write just cow rfl
for the proof terms, or write a little tactic-or-something that packages up the above snippet of code. What's the idiomatic way of doing this?
Andrej Bauer (Nov 10 2021 at 10:14):
Yes, I suppose I am asking how to write such a wrapper. (Or where to read about it, so that I don't have to bother you.)
Andrej Bauer (Nov 10 2021 at 10:26):
Oh my god, an interactive tactic can only have one argument. I so wish there were some documentation. Is there?
Scott Morrison (Nov 10 2021 at 10:29):
No, no, interactive tactics can have many arguments. Sorry, I'm about to head off for the night, but hopefully someone can step in.
Scott Morrison (Nov 10 2021 at 10:29):
There are some excellent video tutorials on metaprogramming by Rob Lewis.
Scott Morrison (Nov 10 2021 at 10:30):
There is a limited tutorial at https://leanprover-community.github.io/extras/tactic_writing.html
Andrej Bauer (Nov 10 2021 at 10:30):
We came up with this:
meta def tactic.interactive.foobar (adj : parse texpr) : tactic unit :=
do { t ← target,
r ← i_to_expr_strict
``(simple_graph.mk
(restrict (%%adj) _)
(begin unfold symmetric, exact cow rfl end)
(begin unfold irreflexive, exact cow rfl end) : %%t
),
exact r
}
Do we go to hell?
Andrej Bauer (Nov 10 2021 at 10:35):
Here's how an interactive tactic is not happy with two arguments:
meta def tactic.interactive.couple (a : parse texpr) (b : parse texpr) : tactic unit :=
do { r ← i_to_expr_strict ``((%%a, %%b)),
exact r}
example: ℕ × ℕ := by couple 5 6
Gabriel Ebner (Nov 10 2021 at 10:38):
Lean parses 5 6
as an application here (and so never gets to b
).
Andrej Bauer (Nov 10 2021 at 10:38):
Yes, I gather that much. How do I get around it?
Gabriel Ebner (Nov 10 2021 at 10:38):
The easiest fix is to add a separator between the two arguments:
import tactic.core
setup_tactic_parser
open tactic
meta def tactic.interactive.couple (a : parse texpr) (_ : parse $ tk ",") (b : parse texpr) : tactic unit :=
do { r ← i_to_expr_strict ``((%%a, %%b)),
exact r}
example: ℕ × ℕ := by couple 5, 6
Kyle Miller (Nov 10 2021 at 16:54):
Andrej Bauer said:
But I cannot change the definition of
simple_graph
in the standard library.
One way around this is to define your own constructor, and you can replace the obviously
with another tactic
structure simple_graph' (V : Type*) :=
(adj : V → V → Prop)
(sym : symmetric adj . obviouslier)
(loopless : irreflexive adj . obviouslier)
def simple_graph.create {V : Type*} (G : simple_graph' V) :
simple_graph V :=
{ adj := G.adj,
sym := G.sym,
loopless := G.loopless }
-- example
def my_complete (V : Type*) : simple_graph V :=
simple_graph.create { adj := ne }
I would have expected the following to work too, but for some reason the tactics fail because their results have metavariables:
def simple_graph.mk' {V : Type*}
(adj : V → V → Prop)
(sym : symmetric adj . obviously)
(loopless : irreflexive adj . obviously) :
simple_graph V :=
{ adj := adj }
def my_complete (V : Type*) : simple_graph V :=
simple_graph.mk' ne
Mario Carneiro (Nov 10 2021 at 17:01):
Another way to make by couple 5 6
work is to parse 5
and 6
at application precedence, using pexpr 1025
instead of texpr
Last updated: Dec 20 2023 at 11:08 UTC