Zulip Chat Archive
Stream: general
Topic: Bytecode warning when defining a yoneda-like functor
Dagur Asgeirsson (Apr 27 2023 at 09:44):
What does this error message even mean? From previous discussions here on Zulip I understand that this often occurs when something that's not a Prop is called lemma and not def, but that's not the case here.
def fin_yoneda (X : Type (u+1)) : Fintype.{u}ᵒᵖ ⥤ Type (u+1) :=
{ obj := λ Y, (unop Y) → X,
map := λ Y Z f g z, g (f.unop z) }
/-
failed to generate bytecode for 'fin_yoneda'
infer type failed, function expected at
f z
term
f
has type
Y ⟶ Z
-/
Yaël Dillies (Apr 27 2023 at 09:45):
What does adding noncomputable
do?
Dagur Asgeirsson (Apr 27 2023 at 09:46):
Nothing :(
Dagur Asgeirsson (Apr 27 2023 at 09:46):
Well I have a "noncomputable theory" at the top, and removing it does nothing
Yaël Dillies (Apr 27 2023 at 09:50):
It looks like it's just having trouble seeing that f : Y ⟶ Z
is a function. What if you type-ascript?
Dagur Asgeirsson (Apr 27 2023 at 09:52):
Like this? It gives the same error.
def fin_yoneda (X : Type (u+1)) : Fintype.{u}ᵒᵖ ⥤ Type (u+1) :=
{ obj := λ Y, (unop Y) → X,
map := λ Y Z f g z, g ((f.unop : (unop Z) → (unop Y)) z) }
Dagur Asgeirsson (Apr 27 2023 at 09:53):
f itself is of course not a function, it's an arrow in the opposite category
Yaël Dillies (Apr 27 2023 at 09:54):
What's the type of all the variables? Can we have a MWE?
Dagur Asgeirsson (Apr 27 2023 at 09:56):
The only variable is X : Type (u+1)
.
Dagur Asgeirsson (Apr 27 2023 at 09:57):
What's even weirder is that my_yoneda
defined below gives the same error message, yet my_yoneda_eq_yoneda
is true:
def my_yoneda (X : Type (u+1)) : (Type (u+1))ᵒᵖ ⥤ Type (u+1) :=
{ obj := λ Y, unop Y ⟶ X,
map := λ Y Y' f g, f.unop ≫ g }
lemma my_yoneda_eq_yoneda (X : Type (u+1)) : my_yoneda X = yoneda.obj X := by refl
Yaël Dillies (Apr 27 2023 at 10:04):
Dagur Ásgeirsson said:
The only variable is
X : Type (u+1)
.
No, but f
, g
, etc... Can you copy the context or, better, give us a #mwe?
Dagur Asgeirsson (Apr 27 2023 at 10:07):
Here is a mwe:
import category_theory.yoneda
import category_theory.Fintype
universe u
open opposite
open category_theory
def my_yoneda (X : Type (u+1)) : (Type (u+1))ᵒᵖ ⥤ Type (u+1) :=
{ obj := λ Y, unop Y ⟶ X,
map := λ Y Y' f g, f.unop ≫ g }
lemma my_yoneda_eq_yoneda (X : Type (u+1)) : my_yoneda X = yoneda.obj X := by refl
def fin_yoneda (X : Type (u+1)) : Fintype.{u}ᵒᵖ ⥤ Type (u+1) :=
{ obj := λ Y, (unop Y) → X,
map := λ Y Z f g z, g ((f.unop : (unop Z) → (unop Y)) z) }
Dagur Asgeirsson (Apr 27 2023 at 10:08):
Y, Z, f, g, z are all bound by the lambda but here is the state after it in fin_yoneda
:
X : Type (u+1),
Y Z : Fintypeᵒᵖ,
f : Y ⟶ Z,
g : ↥(unop Y) → X,
z : ↥(unop Z)
⊢ X
Jon Eugster (Apr 27 2023 at 10:24):
I have no clue about anything here, but I find it interesting that the following seems to work although I would naively expect it to do the same thing:
import category_theory.yoneda
import category_theory.Fintype
universe u
open opposite
def fin_yoneda (X : Type (u+1)) : Fintype.{u}ᵒᵖ ⥤ Type (u+1) :=
{ obj := λ Y, (unop Y) → X,
map := λ Y Z f g z, begin
let f' := (f.unop),
exact g (f' z),
end
}
Eric Wieser (Apr 27 2023 at 10:31):
def my_yoneda (X : Type (u+1)) : (Type (u+1))ᵒᵖ ⥤ Type (u+1) :=
{ obj := λ Y, unop Y ⟶ X,
map := λ Y Y' f g, let f' := f.unop in f' ≫ g }
works too
Dagur Asgeirsson (Apr 27 2023 at 10:31):
Thanks, that's weird. Would be interesting if someone knows why this works
Kyle Miller (Apr 27 2023 at 11:04):
Dagur Ásgeirsson said:
Well I have a "noncomputable theory" at the top, and removing it does nothing
The Lean 3 noncomputability logic is:
- If the function is marked
noncomputable!
, believe the user and skip the rest of these steps. - Determine whether the function should be computable or not.
- If there's no
noncomputable theory
at the top, complain if the user got it wrong (i.e., if they put or didn't putnoncomputable
on this definition correctly).
Kyle Miller (Apr 27 2023 at 11:06):
This means that if you have noncomputable theory
, Lean completely(*) ignores whether you put noncomputable
or not.
(*) Just to complicate things, the equation compiler acts differently depending on whether you add noncomputable
. I think this only really impacts recursive definitions.
Dagur Asgeirsson (Apr 27 2023 at 11:08):
Hmm ok, putting noncomputable!
works:
noncomputable! def fin_yoneda (X : Type (u+1)) : Fintype.{u}ᵒᵖ ⥤ Type (u+1) :=
{ obj := λ Y, (unop Y) → X,
map := λ Y Z f g z, g (f.unop z), }
Kyle Miller (Apr 27 2023 at 11:08):
(deleted: you tried my suggestion already! :racecar:)
Kyle Miller (Apr 27 2023 at 11:09):
Oh, this is a fascinating error:
failed to generate bytecode for 'my_yoneda'
infer type failed, function expected at
f x
term
f
has type
Y ⟶ Y'
Kyle Miller (Apr 27 2023 at 11:11):
I'm not going to go and debug it, but I have a strong suspicion what it is. opposite
is @[irreducible]
, and the core infer_type
algorithm doesn't unfold irreducible definitions when calculating the type. I don't think this error should happen, but I doubt it will be fixed in Lean 3.
Kyle Miller (Apr 27 2023 at 11:18):
Here's what set_option trace.compiler true
reveals about how this function is transformed during compilation:
λ (X : Type (u+1)),
{obj := λ (Y : (Type (u+1))ᵒᵖ), unop Y → X,
map := λ (Y Y' : (Type (u+1))ᵒᵖ) (f : Y ⟶ Y') (g : unop Y ⟶ X) (x : unop Y'), g (f x),
map_id' := my_yoneda._proof_1 X,
map_comp' := my_yoneda._proof_2 X}
Eric Wieser (Apr 27 2023 at 11:23):
I think the definition of docs#quiver.hom.unop is to blame
Kyle Miller (Apr 27 2023 at 11:23):
It inlines the definition of ≫
for the Type
category and simplifies some things until it gets to g (f x)
, but f
isn't a function that can be applied due to irreducibility.
Kyle Miller (Apr 27 2023 at 11:24):
Yeah, it looks like it's inlining hom.unop
but with irreducibility thrown in it's not seeing it as being type correct. (I think arguably the compiler should be able to handle this though.)
Eric Wieser (Apr 27 2023 at 11:24):
hom.unop
should presumably be implemented in terms of composition with op and unop?
Eric Wieser (Apr 27 2023 at 11:29):
Kyle Miller said:
but I have a strong suspicion what it is.
opposite
is@[irreducible]
Indeed, this fixes it
attribute [semireducible] quiver.opposite
Kyle Miller (Apr 27 2023 at 11:30):
I'm not sure there's any fix for hom.unop
that would protect against infer_type
failing
Kyle Miller (Apr 27 2023 at 11:31):
There's a Lean 4 issue tracking what seems to be the same problem.
Eric Wieser (Apr 27 2023 at 11:33):
Trying to wrap it in a structure seems to run into universe issues
Eric Wieser (Apr 27 2023 at 11:34):
Making quiver.opposite
semireducible seems like an obvious fix
Eric Wieser (Apr 27 2023 at 11:35):
I don't see why it makes sense to make it irreducible, it's not guarding a type synonym or anything
Kyle Miller (Apr 27 2023 at 11:41):
There's a different quiver
structure on Type u
vs (Type u)ᵒᵖ
at least, so you don't want opposite
to be unfolded. It also helps protect against composing morphisms that shouldn't be composed
Eric Wieser (Apr 27 2023 at 11:48):
Aren't you describing why opposite
should be irreducible? I don't see why quiver.opposite
should be irreducible
Eric Wieser (Apr 27 2023 at 11:48):
That feels like making docs#mul_opposite.has_mul irreducible, which we don't do
Kyle Miller (Apr 27 2023 at 11:52):
Oh, I see. I think quiver.opposite
being irreducible is to make it so that you can't see that the hom sets are pi types, that way you can put instances on them that are different from other pi type instances (but I don't really know the justification).
Kyle Miller (Apr 27 2023 at 11:56):
Here's the commit that made it irreducible: https://github.com/leanprover-community/mathlib/commit/042c290dac25b5f1c77255f1039fae301774d6cf
Eric Wieser (Apr 27 2023 at 12:47):
I'm afraid I don't see what you mean by "see that the hom sets are pi types"
Last updated: Dec 20 2023 at 11:08 UTC