Zulip Chat Archive

Stream: lean4

Topic: Should Id be a structure?


Eric Wieser (Feb 26 2026 at 03:04):

It's very easy to forget Id.run and pure when working with the Id monad, resulting in defeq issues when silently casting between X and Id X. While core is now mostly free of these as of lean4#7352, it's still easy for them to end up reappearing in downstream projects, which lead users down dead ends like simp [Id.run, Pure.pure, Bind.bind], leaving them with a bad goal state.

Should Id be redefined as

structure Id (X : Type _) where
  /-- Not simp-normal, use Pure.pure instead. -/
  protected pure ::
  run : X

instance : Pure Id where pure := Id.pure

@[simp] theorem Id.pure_eq : Id.pure = Pure.pure := rfl

such that it is impossible to make this mistake?

Niels Voss (Feb 26 2026 at 03:51):

What's the difference between using a single element structure and removing @[expose] as a way to prevent defeqs?

Yury G. Kudryashov (Feb 26 2026 at 03:56):

With a 1-field structure, you still have .mk a.run = a as a defeq.

Niels Voss (Feb 26 2026 at 04:07):

Another difference is that for the 1-field structure, Id X = X (or equivalently, Id = id) becomes independent of Lean, which occasionally matters

Eric Wieser (Feb 26 2026 at 05:14):

Yury G. Kudryashov said:

With a 1-field structure, you still have .mk a.run = a as a defeq.

run (pure x) = x is the one we care about

Tomas Skrivan (Feb 26 2026 at 08:04):

YES please! When I was implementing automatic differentiation for monadic code the defeq abuse was a major pain point. At some point I just gave up an defined my own id monad.


Last updated: Feb 28 2026 at 14:05 UTC