Zulip Chat Archive

Stream: mathlib4

Topic: Why some results require both Unique and Fintype


Jz Pan (Apr 08 2025 at 07:38):

A search through loogle reveals that some results in mathlib requires both Unique and Fintype. What is the reason behind that? There is already an instance Unique -> Fintype in mathlib. So I think providing both will lead to a diamond, isn't it? If I define something which requires Fintype, and want to state some results of it requiring Unique, should I add both of Unique and Fintype as assumptions?

Ruben Van de Velde (Apr 08 2025 at 07:53):

It seems more likely that this is to avoid "diamonds" (not quite diamonds in this case). I can try to make an example in a bit

Edward van de Meent (Apr 08 2025 at 10:25):

@loogle Unique, Fintype

loogle (Apr 08 2025 at 10:25):

:search: Finset.univ_unique, Unique.fintype, and 46 more

Edward van de Meent (Apr 08 2025 at 10:26):

ah, but these say different things nope, i thought Unique was a Prop, but it isn't

Aaron Liu (Apr 08 2025 at 10:30):

The Prop-version is Nonempty + Subsingleton

Ruben Van de Velde (Apr 08 2025 at 10:37):

Hmm, I thought this would fail, but it doesn't.

import Mathlib

inductive I | a

instance : Unique I where
  default := I.a
  uniq x := by cases x; rfl

instance : Fintype I where
  elems := {I.a}
  complete x := by cases x; simp

lemma test {α : Type*} [Unique α] : Fintype.card α = 1 := by -- this is about Unique.fintype
  sorry

example : Fintype.card I = 1 := by
  rw [test]

Edward van de Meent (Apr 08 2025 at 10:37):

there is extra support for definitionally subsingleton types, i think...

Edward van de Meent (Apr 08 2025 at 10:38):

possibly a simple fix: add a falso : Empty -> I branch

Edward van de Meent (Apr 08 2025 at 10:49):

this should demonstrate the possible diamond i think:

import Mathlib

inductive I
  | a
  | falso (_:False) : I

instance : Unique I where
  default := I.a
  uniq x := by
    cases x
    · rfl
    · contradiction

noncomputable def i : I := Classical.choice ⟨.a

noncomputable instance noninstance_fintype : Fintype I where
  elems := {i}
  complete x := by
    simp only [Finset.mem_singleton,Unique.eq_default]

lemma test {α : Type*} [Unique α] : Fintype.card α = 1 := by -- this is about Unique.fintype
  rfl -- not important

example : Fintype.card I = 1 := by
  rw [test]

Edward van de Meent (Apr 08 2025 at 10:54):

the funny thing is that this is no longer an issue when you remove the | falso branch and the . contradiction proof, demonstrating leans internal check for subsingleton types

Edward van de Meent (Apr 08 2025 at 10:54):

this issue can also occur without using Classical i think, let me see if i can cook up an example

Aaron Liu (Apr 08 2025 at 10:59):

Edward van de Meent said:

there is extra support for definitionally subsingleton types, i think...

They get structure-eta expanded into a structure with no fields, so any pair is equal.

Edward van de Meent (Apr 08 2025 at 11:01):

here's an example which uses Quot.sound instead, in a way that the concrete value is still reducible and computable:

import Mathlib

inductive I'
  | a
  | b

def I := Quot (fun (_ : I') _ => True)

instance : Unique I where
  default := Quot.mk _ I'.a
  uniq x := by
    apply Quot.ind _ x
    intro _
    exact Quot.sound trivial

noncomputable def i : I := Quot.mk _ I'.b

noncomputable instance bad_instance : Fintype I where
  elems := {i}
  complete x := by
    simp only [Finset.mem_singleton,Unique.eq_default]

lemma test {α : Type*} [Unique α] : Fintype.card α = 1 := by -- this is about Unique.fintype
  rfl -- not important

example : Fintype.card I = 1 := by
  rw [test]

Aaron Liu (Apr 08 2025 at 11:13):

Edward van de Meent said:

there is extra support for definitionally subsingleton types, i think...

You can get definitionally subsingleton types that don't have the property that any pair is defeq (for example, build a type version of docs#Acc)

Ruben Van de Velde (Apr 08 2025 at 11:17):

Nice tricks!


Last updated: May 02 2025 at 03:31 UTC