Zulip Chat Archive

Stream: metaprogramming / tactics

Topic: tactics for unfolding parameters defined in structure


Bach Hoang (Jun 09 2025 at 22:13):

Hi,

I have a question about how to unfold the parameters that is already defined in the structure. Right now I have a type that is built by structure as follow :

structure State where
  labels     : String
  val_labels : List String
  typeMap    : List (String × Type)
  type       : String  Type := fun s =>
    match typeMap.find? (fun p => p.fst = s) with
    | some (_, ty) => ty
    | none => Unit
  val        : List ((s : String) × type s)
  lemma_1    :  x  val,  y  typeMap, x.fst = y.fst
  lemma_2    :  x  typeMap,  y  val, x.fst = y.fst

And right now, I have a result that I need to prove, similar to below

theorem result (X : State) (name : String) : X.type name = Unit := by sorry

, which will require me to unfold the function "type" in State type. But I have tried multiple tactics, including simp, unfold, delta, and they does not reveal the "type" function inside State.

Can you suggest what should I do to resolve this problem ? Thanks

Aaron Liu (Jun 09 2025 at 22:18):

You can set the type field to whatever you want, it doesn't have to be what you put down

Aaron Liu (Jun 09 2025 at 22:21):

For example here I override the default value with my own implementation

example : State where
  labels := "dummy_labels"
  val_labels := ["label_zero", "label_one"]
  typeMap := [("type_zero", Nat), ("type_one", Int × Bool), ("type_two", Unit)]
  type := fun _ => Nat
  val := ["type_zero", 17, "type_two", 8, "type_one", 777, "type_one", 42]
  lemma_1 := by decide
  lemma_2 := by decide

Kyle Miller (Jun 09 2025 at 23:44):

What you need is a feature that doesn't exist, but I hope it will at some point since many people tend to get confused about default values, and there's good reason to be able to define some fields while defining others.

This is what the not-yet-existing feature would look like:

structure State where
  labels     : String
  val_labels : List String
  typeMap    : List (String × Type)
  let type   : String  Type := fun s =>
    match typeMap.find? (fun p => p.fst = s) with
    | some (_, ty) => ty
    | none => Unit
  val        : List ((s : String) × type s)
  lemma_1    :  x  val,  y  typeMap, x.fst = y.fst
  lemma_2    :  x  typeMap,  y  val, x.fst = y.fst

Kyle Miller (Jun 09 2025 at 23:46):

It's possible to simulate this by breaking the structure definition into two:

structure PreState where
  labels     : String
  val_labels : List String
  typeMap    : List (String × Type)

def PreState.type (st : PreState) (s : String) : Type :=
  match st.typeMap.find? (fun p => p.fst = s) with
  | some (_, ty) => ty
  | none => Unit

structure State extends PreState where
  val        : List ((s : String) × toPreState.type s)
  lemma_1    :  x  val,  y  typeMap, x.fst = y.fst
  lemma_2    :  x  typeMap,  y  val, x.fst = y.fst

Last updated: Dec 20 2025 at 21:32 UTC