Zulip Chat Archive

Stream: lean4

Topic: typeclass inference not seeing through reducible definition


Kevin Buzzard (May 05 2023 at 17:49):

In Lean 3 this works:

-- Lean 3
universes w v u

class Category (V : Type u) :=
(Hom : V  V  Sort v)

instance : Category (Type u) :=
{ Hom := λ v w, v  w }

open Category

universes u₁ v₁ u₂ v₂

structure Functor' (V : Type u₁) [Category.{v₁} V] (W : Type u₂) [Category.{v₂} W]

infixr `  `:26 := Functor'       -- type as \func --

variables (C : Type u) [Category.{v} C]

def Functor.id : C  C := {}

notation `𝟭` := Functor.id -- Type this as `\sb1`

class ConcreteCategory (C : Type u) [Category.{v} C] :=
(Forget : C  Type w)

@[reducible]
def forget (C : Type u) [Category.{v} C] [ConcreteCategory.{w} C] : C  Type w :=
  ConcreteCategory.Forget

instance ConcreteCategory.types : ConcreteCategory (Type u) :=
{ Forget := 𝟭 _ }

class ReflectsLimits {C : Type u₁} {D : Type u₂} [Category.{v₁} C] [Category.{v₂} D] (F : C  D)

instance idReflectsLimits {C : Type u} [Category.{v} C] : ReflectsLimits (𝟭 C) := {}

example : ReflectsLimits (forget (Type u)) := idReflectsLimits -- works

example : ReflectsLimits (forget (Type u)) := infer_instance -- works

In particular typeclass inference can solve ReflectsLimits (forget (Type u)) (and does, in mathlib). The analogous Lean 4 code doesn't work:

-- Lean 4
universe w v u

class Category (V : Type u) where
  Hom : V  V  Sort v

instance : Category (Type u) where
  Hom := λ v w => v  w

open Category

structure Functor' (V : Type u₁) [Category.{v₁} V] (W : Type u₂) [Category.{v₂} W] where

infixr:26 " ⥤ " => Functor' -- type as \func

variable (C : Type u) [Category.{v} C]

def Functor.id : C  C where

notation "𝟭" => Functor.id -- Type this as `\sb1`

class ConcreteCategory (C : Type u) [Category.{v} C] where
  /-- We have a functor to Type -/
  Forget : C  Type w

@[reducible]
def forget (C : Type u) [Category.{v} C] [ConcreteCategory.{w} C] : C  Type w :=
  ConcreteCategory.Forget

instance ConcreteCategory.types : ConcreteCategory (Type u) where
  Forget := 𝟭 _

class ReflectsLimits {C : Type u₁} {D : Type u₂} [Category.{v₁} C] [Category.{v₂} D] (F : C  D) where

instance idReflectsLimits {C : Type u} [Category.{v} C] : ReflectsLimits (𝟭 C) where

example : ReflectsLimits (forget (Type u)) := idReflectsLimits -- works

#synth ReflectsLimits (forget (Type u)) -- fails

Is there some way I can make things more [reducible] or something, in order to get this to work? The point is that forget (Type u) is defeq to 𝟭 _ and forget is reducible, but it's not enough in Lean 4. If I can't get this working somehow then I'm going to have to add a bunch of instances to some file in the port to work around this, which is certainly a solution but it's kind of a last resort.

Adam Topaz (May 05 2023 at 18:04):

Adding reducible to literally everything in this file doesn't seem to work. So I guess the answer is no, it's not possible?

Adam Topaz (May 05 2023 at 18:05):

Maybe there's some unification hint that would make this work? Let me try

Adam Topaz (May 05 2023 at 18:11):

oops: https://leanprover.github.io/lean4/doc/unifhint.html?highlight=hint#unification-hints

Adam Topaz (May 05 2023 at 18:12):

I realized I don't actually know how to make unification hints :(

Kevin Buzzard (May 05 2023 at 18:13):

Maybe it's just the same as in Lean 3! Did you know how to do it in Lean 3? (I certainly didn't...)

Adam Topaz (May 05 2023 at 18:14):

No, I didn't :see_no_evil:

Adam Topaz (May 05 2023 at 19:05):

Okay, I don't have time to try to figure out how (or if) unification hints can help here. But I think it would be very interesting to see whether they do actually solve this issue! Hopefully someone who knows what they're doing with unification hints can help?

Kevin Buzzard (May 08 2023 at 11:35):

Here's how they work @Adam Topaz :

structure Magma where
  α : Type
  mul : α  α  α

infixl:70 (priority := high) "**" => Magma.mul _

-- #check (3 : Nat) ** (3 : Nat) -- fails

def Nat.Magma : Magma where
  α := Nat
  mul a b := Nat.mul a b

unif_hint (S : Magma) where
  S  Nat.Magma  S.α  Nat

#check (3 : Nat) ** (3 : Nat) -- works

Eric Wieser (May 08 2023 at 11:58):

Kevin Buzzard said:

Maybe it's just the same as in Lean 3! Did you know how to do it in Lean 3? (I certainly didn't...)

I think in Lean3 they only worked in Type 0

Eric Wieser (May 08 2023 at 12:00):

Adam Topaz said:

Adding reducible to literally everything in this file doesn't seem to work. So I guess the answer is no, it's not possible?

attribute [reducible] ConcreteCategory.Forget ConcreteCategory.types works

Scott Morrison (May 08 2023 at 12:33):

@Kevin Buzzard, I think for your example to make sense, you should move the failing #check below def Nat.Magma!

Scott Morrison (May 08 2023 at 12:36):

Do you have a good heuristic for remembering in

unif_hint where
  W  X  Y  Z

the respective roles of W X Y Z? It seems from your example that one should read this as "if you are trying to match Z with Y, instead try match X with W", which is disconcertingly right-to-left! :-)

Kevin Buzzard (May 08 2023 at 12:40):

Moving the check to just after Nat.magma doesn't make it work, fortunately :-) It seems that it's possible to swap Y,Z and also X,W. I'm just putting together the very little stuff that other people have written about unification hints, I have no more understanding of what's going on than you.

Adam Topaz (May 08 2023 at 13:57):

@Kevin Buzzard that’s the sort of example I actually did figure out :) Leo mentioned this example (and related ones) in his ICERM talk, for example. But I still couldn’t figure out how to make progress with the ReflectLimits issue above unification hints. Could you find some way to make that work?

@Eric Wieser I thought I tied that as well, but maybe I’m misremembering. In any case, it’s not clear to me whether tagging things as reducible is the right approach in this case.

Eric Wieser (May 08 2023 at 13:57):

I think it's sensible to make defs that resolve to types reducible

Eric Wieser (May 08 2023 at 13:58):

In lean3 we got away with not doing so because TC search would (sometimes) ignore reducibility and reduce things anyway

Eric Wieser (May 08 2023 at 21:56):

!4#3857


Last updated: Dec 20 2023 at 11:08 UTC