Zulip Chat Archive

Stream: new members

Topic: unfold vs dsimp


Kevin Cheung (Feb 27 2024 at 14:06):

I know that the documentation discourages the use of Set.inter. But I would like to know why in the following dsimp works but unfold doesn't:

example : s  u  u  s := by
  dsimp [(·  ·)]
  sorry

example : s  u  u  s := by
  unfold (·  ·)
  sorry

In the second version, Lean complains about unexpected token '('. Is it simply a limitation of unfold that it cannot unfold operators?

Timo Carlin-Burns (Feb 27 2024 at 19:19):

I'm surprised either of those work. The only good way to unfold notation that I've learned is to define a custom lemma like docs#Set.inter_def which can be proved by rfl. It seems like simp has some special support for the · notation for defining functions.

import Mathlib.Data.Set.Basic

variable (s t : Set α)

-- This is the only one I would've expected to work. I thought `simp` and `unfold` only worked with declaration names.
example : s  u  u  s := by
  dsimp [Inter.inter] -- unfolds to `Set.inter`
  sorry

example : s  u  u  s := by
  dsimp [(Inter.inter · ·)] -- unfolds to `Set.inter`
  sorry

example : s  u  u  s := by
  dsimp [(·  ·)] -- unfolds to `Set.inter`
  sorry

example : s  u  u  s := by
  dsimp [(fun x y => Inter.inter x y)] -- invalid 'simp', proposition expected
  sorry

example : s  u  u  s := by
  dsimp [(Inter.inter)] -- invalid 'simp', proposition expected
  sorry

example : s  u  u  s := by
  dsimp [((·  ·))] -- invalid 'simp', proposition expected
  sorry

Kevin Cheung (Feb 27 2024 at 22:48):

Interesting. Replacing dsimp [Inter.inter] with unfold Inter.inter gives the goal instInterSet.1 s u ⊆ instInterSet.1 u s, not Set.inter s u ⊆ Set.inter u s. I am now utterly confused. Why instInterSet.1 here?

Kyle Miller (Feb 27 2024 at 22:53):

docs#Inter is a "notation typeclass" that provides the notation to whichever types implement the instance.

docs#Set.instInterSet is the instance for Set. When you unfold Inter.inter, you're seeing its definition, which is that it gets the definition from the instance.

Kyle Miller (Feb 27 2024 at 22:54):

If you do unfold_projs (mathlib tactic) it will unfold instInterSet.1 s

Kyle Miller (Feb 27 2024 at 22:56):

The limitation of unfold is that the syntax expects a sequence of identifiers

Kevin Cheung (Feb 27 2024 at 22:56):

So unfold cannot unfold operators?

Kevin Cheung (Feb 27 2024 at 22:57):

It seems that dsimp is more powerful than unfold. Are there reasons for using unfold but not dsimp?

Kyle Miller (Feb 27 2024 at 22:57):

It can, if you give it the underlying identifier. Here it's Inter.inter (you can check that by hovering over the notation)

Kevin Cheung (Feb 27 2024 at 22:58):

When I hover over , I saw only the following:

Set α

a  b is the intersection of a and b.

Type  using \i or \inter or \intersection or \cap

Kevin Cheung (Feb 27 2024 at 22:59):

Oh. I have to hover in the Infoview to see the Inter.inter

Kyle Miller (Feb 27 2024 at 22:59):

You can also "go to declaration" if you right click on it in the source

Kevin Cheung (Feb 27 2024 at 23:01):

Thanks for the tip! I was trying so hard looking into the documentation to see where intersection is defined.

Timo Carlin-Burns (Feb 27 2024 at 23:17):

Kyle, do you happen to know why (f · ·) is behaving differently from (fun x y => f x y) here? Is simp special casing the · syntax? Or does the · syntax have some eta-reduction built in?

Kyle Miller (Feb 27 2024 at 23:26):

Yeah, there's a special case for cdot syntax for simp (docs#Lean.Elab.Term.elabCDotFunctionAlias?)


Last updated: May 02 2025 at 03:31 UTC