Zulip Chat Archive

Stream: lean4

Topic: make binder implicit in CoeFun


Kevin Buzzard (Nov 29 2022 at 20:45):

Is this possible in Lean 4? It worked in Lean 3:

-- lean 4
structure Foo (F G : Type  Type) where
  app :  α : Type, F α  G α -- explicit

variable (F : Type  Type)
variable (G : Type  Type)

-- make α implicit in coercion to fun
instance : CoeFun (Foo F G) fun _ =>  {α : Type}, F α  G α := Foo.app

variable (f : Foo F G) (x : F Nat)

#check f x -- fails
/-
application type mismatch
  Foo.app f x
argument
  x
has type
  F Nat : Type
but is expected to have type
  Type : Type 1
-/

#check f Nat x -- G Nat

Kevin Buzzard (Nov 29 2022 at 20:49):

-- lean 3
structure foo (F G : Type  Type) :=
(app :  α : Type, F α  G α) -- explicit

variable (F : Type  Type)
variable (G : Type  Type)

-- make α implicit in coercion to fun
instance : has_coe_to_fun (foo F G) (λ _, Π {α}, F α  G α) :=
foo.app

variables (f : foo F G) (x : F )

#check f x -- works

Gabriel Ebner (Nov 29 2022 at 21:14):

No this doesn't work, you can't change the type with coercions.

Gabriel Ebner (Nov 29 2022 at 21:15):

You'd need to an auxiliary definition for that.

Kevin Buzzard (Nov 29 2022 at 22:03):

When things like this happen during porting (stuff which would work in lean 3 but not in lean 4) I never know whether to ask about them or just work around them.. I'll work around this one!

Leonardo de Moura (Nov 29 2022 at 22:06):

Recall that coercions are eagerly expanded by Lean 4.

Kevin Buzzard (Nov 29 2022 at 22:22):

Yeah but in my mental model of elaboration (which is poor) Foo.app is being unified to have type ∀ {α : Type}, F α → G α...I guess what I'm actually saying is that I don't really even understand how binders interact with type theory. My understanding is that ∀ {α : Type}, F α → G α and ∀ (α : Type), F α → G α are syntactically equal as far as type theory goes, and Foo.app is being coerced into having type ∀ {α : Type}, F α → G α but I have no clue about whether that coercion "sticks" when the coercion to function is instantiated; it seemed to stick in Lean 3 but not in Lean 4, is my mental model.

Adam Topaz (Nov 29 2022 at 22:27):

Is there any issue with making the following modification?

-- lean 4
structure Foo (F G : Type  Type) where
  app :  {α : Type}, F α  G α -- implicit

variable (F : Type  Type)
variable (G : Type  Type)

-- make α implicit in coercion to fun
instance : CoeFun (Foo F G) fun _ =>  {α : Type}, F α  G α := Foo.app

variable (f : Foo F G) (x : F Nat)

#check f x -- works

Adam Topaz (Nov 29 2022 at 22:29):

Or this

-- lean 4
structure Foo (F G : Type  Type) where
  app :  α : Type, F α  G α -- explicit

variable (F : Type  Type)
variable (G : Type  Type)

-- make α implicit in coercion to fun
instance : CoeFun (Foo F G) fun _ =>  {α : Type}, F α  G α := fun η => η.app _

variable (f : Foo F G) (x : F Nat)

#check f x -- works

Eric Wieser (Nov 29 2022 at 22:30):

@Adam Topaz , your --explicit comment is now wrong, right?

Adam Topaz (Nov 29 2022 at 22:30):

yeah ;)

Adam Topaz (Nov 29 2022 at 22:30):

(fixed)

Leonardo de Moura (Nov 29 2022 at 22:31):

@Kevin Buzzard If you add a set_option pp.all true in the Lean 4 and Lean 3 files, you will see the difference
Lean 3

set_option pp.all true
#check f x -- works
-- @coe_fn.{2 2} (foo F G) (λ (_x : foo F G), Π {α : Type}, F α → G α) (foo.has_coe_to_fun F G) f nat x : G nat

Lean 4

set_option pp.all true
#check f Nat x -- G Nat
-- @Foo.app F G f Nat x : G Nat

Note that the Lean 3 version contains the coe_fn auxiliary function.

Kevin Buzzard (Nov 29 2022 at 22:35):

@Adam Topaz the issue with changing the binders is that I think the agreement is that we try to make the port as faithful as possible right now, or else this will just lead to confusion down the line. In Lean 3 the app has an explicit alpha and the coercion has an implicit one, so your second suggestion is what I've gone with.


Last updated: Dec 20 2023 at 11:08 UTC