Zulip Chat Archive
Stream: new members
Topic: Is there a variant of repr that "prints the type"?
Eduardo Ochs (Jun 12 2024 at 02:02):
I wrote my first DSL a few days ago - here, screenshot - and I'm in a stage in which I still have to decompose each example in the Metaprogramming book into 10 smaller snippets to understand what is going on in it... and this looks like a good way to explore (specific) Syntax/TSyntax objects:
import Lean
open Lean Elab Command
elab "#withstring " x:str : command =>
match x with
| `("a") => logInfo x
| `("b") => do { logInfo x; logInfo (repr x) }
| `("c") => do { logInfo x; logInfo (repr x.raw) }
| _ => Elab.throwUnsupportedSyntax
#withstring "a"
#withstring "b"
#withstring "c"
I know that repr o
converts o
to its repr as a string, and #check o
prints o and its type - but #check
is a command, so it has access to the current context...
Is there a function that receives an object o
and returns its type converted to a string?
Damiano Testa (Jun 12 2024 at 02:23):
Could you give an example of an o
and what you would like to obtain?
Eduardo Ochs (Jun 12 2024 at 03:33):
Oops, sorry!
In my example above the #withstring "b"
displays repr x
without saying that its type is TSyntax `str
.
Kyle Miller (Jun 12 2024 at 04:16):
Do you need a string for your particular application? Or is this for use with logInfo
?
Eduardo Ochs (Jun 12 2024 at 08:41):
It's for logInfo! I asked for the type "as a string" because that seemed to be general enough...
Eduardo Ochs (Jun 12 2024 at 08:44):
...in the sense of: "people that start from the code that returns the type as a string and then discover how that type was represented before being converted into a string".
Eduardo Ochs (Jun 12 2024 at 08:50):
I was planning to write a blog post, or something like that looks like one, to explain what I did to decypher some examples of the Metaprogramming book, and why I am still stuck at some other examples... would that be useful?
Kyle Miller (Jun 12 2024 at 17:15):
Few things use repr
, as it turns out. It's mostly for the case where you have a runtime representation that you want to turn into a string representation, where in metaprogramming you already are working with an Expr
representation of the object rather than a runtime representation, and the Expr
representation is "richer" in a number of ways.
For example, with the Expr
representation, you can compute the type of the term (as an Expr
).
For repr
, if you really want to work with it, you would have to make your own version that also includes a reprTypePrec
field for creating a representation of the type.
Here's a simple #check
command:
import Lean
open Lean Elab Command Meta
elab "#my_check " t:term : command => do
runTermElabM fun _ => do -- go into term elaboration mode after processing any `variables` commands
let e ← Term.elabTermAndSynthesize t none -- elaborate `t` and run all elaboration tasks to completion
let eTy ← inferType e -- compute the type of `e`
logInfo m!"{e} : {eTy}" -- log a MessageData with `e` and `eTy` embedded into it
#my_check "s"
-- "s" : String
The logInfo
line is not using repr
at all. Instead, e
and eTy
are both Expr
s, they are being embedded into the MessageData
, and then, eventually, they are pretty printed (not using repr
) in such a way that you can hover over them in the InfoView and get informational popups.
Eduardo Ochs (Jun 12 2024 at 18:44):
Wow! That's exactly what I was looking for! Thanks! =)
Eduardo Ochs (Jun 12 2024 at 18:48):
...except for one thing: sometimes I need to inspect objects whose types have metavariables - like here, in which #my_check
gives the error typeclass instance problem is stuck, it is often due to metavariables
but #check
handles that in a nice way...
#check do logInfo "foo"
#my_check do logInfo "foo"
Is that trivial to fix? How?
Kyle Miller (Jun 12 2024 at 18:52):
The "typeclass instance problem is stuck" error comes from elabTermAndSynthesize
. You can do some of it manually to adjust some configuration:
import Lean
open Lean Elab Command Meta
elab "#my_check " t:term : command => do
runTermElabM fun _ => do -- go into term elaboration mode after processing any `variables` commands
let e ← Term.elabTerm t none -- elaborate `t` and run all elaboration tasks to completion
Term.synthesizeSyntheticMVars (postpone := .no) (ignoreStuckTC := true)
let eTy ← inferType e -- compute the type of `e`
logInfo m!"{e} : {eTy}" -- log a MessageData with `e` and `eTy` embedded into it
#my_check do logInfo "foo"
-- logInfo ((MessageData.ofFormat ∘ format) "foo") : ?m.983 Unit
Kyle Miller (Jun 12 2024 at 18:53):
If you right click on #check
and "Go to Definition" you can see how #check
does it.
Last updated: May 02 2025 at 03:31 UTC