Zulip Chat Archive
Stream: general
Topic: Making custom pretty-printers work in tactic mode
Wojciech Nawrocki (Jul 13 2019 at 12:22):
How can I force Lean to use my pretty-printer when printing types/expressions in the tactic state? I defined all instances I could think of but it still insists on using the full constructor form. (I don't want to use infix
/notation
in this case).
inductive Expr | Mul: Expr → Expr → Expr | Const (n: ℕ): Expr open Expr def Expr.to_string: Expr → string | (Mul e1 e2) := "(" ++ e1.to_string ++ "*" ++ e2.to_string ++ ")" | (Const n) := has_to_string.to_string n instance : has_to_string Expr := ⟨Expr.to_string⟩ instance : has_repr Expr := ⟨Expr.to_string⟩ /- NB this instance is invalid, eval (repr e) = e doesn't hold -/ meta instance : has_to_format Expr := ⟨λe, ↑e.to_string⟩ #eval (Mul (Const 0) (Const 1)) -- (0*1) :) example : true := begin let x := (Mul (Const 0) (Const 1)), /- Tactic State: x : Expr := Mul (Const 0) (Const 1) -- :( ⊢ true -/ end
Marc Huisinga (Jul 13 2019 at 13:04):
i'm not sure if you can do that, what if a parameter to Expr isn't fully evaluated in the tactic state? what should to_string do then?
the usual way to do this is to use the notation command - notations will show up in the tactic state.
according to @Sebastian Ullrich, one can also write some kind of parser, but i've never done that in lean and i'm not sure if that shows up in the tactic state.
edit: i just realized that i don't really understand to_format, so disregard what i said for to_format ...
Wojciech Nawrocki (Jul 13 2019 at 14:19):
Ah okay, I see what you mean. There could be something like maybe_uneval_to_string: maybe_uneval mytype -> string
which would also have to handle cases where the value is a metavariable/let-binding/etc but with the current system, to_string
expects the whole value to be well-defined. to_format
is basically the same in this respect - it differs only in allowing finer control over the formatting.
Sebastian Ullrich (Jul 13 2019 at 17:33):
You most certainly do not want to evaluate things in the tactic state in order to print them; the most interesting parts in there usually are not constructors
Sebastian Ullrich (Jul 13 2019 at 17:34):
Apart from notations, the only customization Lean 3 gives you for tactic state reporting is overriding the has_to_format tactic_state
instance - but then you'll have to format the whole goal yourself
Wojciech Nawrocki (Jul 13 2019 at 17:42):
I agree that evaluation is not the way to go, but I think there would still be a lot of value in pretty printers that can handle metavariables, local constants and so on. Thanks to notation commands we can get nice output like |- x*(y*z) = x*y*z
, but notation is limited - for example, if I wanted to print a tree structure in some form within the goal:
|- +- root +- left +- leaf1 +- leaf2 +- right = some_other_tree
Marc Huisinga (Jul 13 2019 at 17:45):
Apart from notations, the only customization Lean 3 gives you for tactic state reporting is overriding the
has_to_format tactic_state
instance - but then you'll have to format the whole goal yourself
aha! i was getting really confused when i tried to implement has_to_format similar to other inductive types like list in format.lean and it wouldn't work.
Sebastian Ullrich (Jul 13 2019 at 17:55):
I agree that evaluation is not the way to go
Right, so what you'd want instead is a reflected analog to has_to_format
- for a given type (identified by its constant name
), take a term (expr
) of that type and return its format
. That is how notations pretty-printing in Lean 3 works, it's just missing such a user hook.
Simon Hudon (Jul 14 2019 at 14:44):
@Sebastian Ullrich I just got this PR in #1222 which among other things lets you use tactic
to pretty print stuff (e.g. trace!"expr: {e}; type: {infer_type e}"
). Are you saying that's definitely a bad idea?
Sebastian Ullrich (Jul 14 2019 at 15:49):
No, has_to_tactic_format
is fine. This was about using evaluation for printing terms.
Last updated: Dec 20 2023 at 11:08 UTC