Zulip Chat Archive

Stream: lean4

Topic: inspect expressions


Damiano Testa (Aug 01 2023 at 10:46):

Dear All,

I often find myself wanting how a term of some inductive type is build out of its constructors. Is there a command that prints this information?

I would especially like this to work on Exprs, since my main motivation is as a help to debug meta-code.

My current approach is a simple-minded recursion into Exprs. Here is an example:

example : 3  0 := by
  inspect
/-
inspect: '3 ≠ 0'

'Ne' -- app
|-'Nat' -- const
|-'OfNat.ofNat' -- app
| |-'Nat' -- const
| |-'3' -- natLit
| |-'instOfNatNat' -- app
| | |-'3' -- natLit
|-'OfNat.ofNat' -- app
| |-'Nat' -- const
| |-'0' -- natLit
| |-'instOfNatNat' -- app
| | |-'0' -- natLit
-/

Damiano Testa (Aug 01 2023 at 10:47):

Before I try anything deeper, is this already available, in some form or other?

Thanks!

Damiano Testa (Aug 01 2023 at 10:55):

In case you are wondering, this is the simple-minded code that I used for the example above:

inspect

Kyle Miller (Aug 01 2023 at 11:00):

Mathlib.Tactic.Explode has a command that's meant for showing the structure of proofs. By default it filters out anything that's not a proof though, and it flattens out the hierarchical structure of an expression, which is probably not what you want.

Kyle Miller (Aug 01 2023 at 11:04):

Here's something that simple that also gives you the Expr structure of an expression:

import Mathlib.Tactic.ToExpr

open Lean Elab Tactic

elab "inspect" : tactic =>
  withMainContext do
    let ty  instantiateMVars ( getMainTarget)
    logInfo m!"{toExpr ty}"

example : 3  0 := by
  inspect
/-
Expr.app
  (Expr.app (Expr.app (Expr.const `Ne [Level.succ Level.zero]) (Expr.const `Nat []))
    (Expr.app
      (Expr.app (Expr.app (Expr.const `OfNat.ofNat [Level.zero]) (Expr.const `Nat [])) (Expr.lit (Literal.natVal 3)))
      (Expr.app (Expr.const `instOfNatNat []) (Expr.lit (Literal.natVal 3)))))
  (Expr.app
    (Expr.app (Expr.app (Expr.const `OfNat.ofNat [Level.zero]) (Expr.const `Nat [])) (Expr.lit (Literal.natVal 0)))
    (Expr.app (Expr.const `instOfNatNat []) (Expr.lit (Literal.natVal 0))))
-/

Damiano Testa (Aug 01 2023 at 11:06):

Kyle, thank you! This is close, and, had I known about it, I would have probably stuck with ExplodeToExpr.

Damiano Testa (Aug 01 2023 at 11:06):

I think that I prefer inspect, but ExplodeToExpr is good to know!

Kyle Miller (Aug 01 2023 at 11:07):

(It might be nice to tweak the ToExpr instance to use mkApp* functions. It's a derived instance though, so I'm not sure the best way to do this...)

Damiano Testa (Aug 01 2023 at 11:07):

(Mostly, my preference is out of aesthetics, the information about proofs is likely rarely relevant for my intended application anyway.)

Damiano Testa (Aug 01 2023 at 11:14):

As far as I can tell, ToExpr works for several of the other inductives that I would like. For the moment, I will debug with a combination of inspect and ToExpr.

To be fair, it is rare that I need to inspect much more than just the head-symbol, but I still find that displaying the information line-by-line is better suited for my application.


Last updated: Dec 20 2023 at 11:08 UTC