Zulip Chat Archive
Stream: lean4
Topic: cannot find synthesization order for instance
Tomas Skrivan (Apr 24 2023 at 15:31):
I have updated to a newer version of Lean and I'm getting an error I have not seen before.
This code
class Foo (A : Type) (B : outParam Type)
class Bar (A : outParam Type) (B : Type) extends Foo A B
Produces
cannot find synthesization order for instance @Bar.toFoo with type
{A : outParam Type} → {B : Type} → [self : Bar A B] → Foo A B
all remaining arguments have metavariables:
Bar A ?B
Swapping outParam
might seem to be quite suspicious. My application of this is:
Foo A B
says thatA
is a container with valuesB
Bar A B
says thatA
is the canonical container with valuesB
More concretely, I have
class GenericArrayType (Cont : Type u) (Idx : outParam $ Type v ) (Elem : outParam $ Type w)
...
and
class ArrayType (Cont : outParam Type) (Idx Elem: Type) extends GenericArrayType Cont Idx Elem
I use ArrayType
in notation Elem^Idx
which just fetches the corresponding Cont
Reid Barton (Apr 24 2023 at 16:04):
That's also a word I haven't seen before
Tomas Skrivan (Apr 24 2023 at 16:09):
It is causing problems when just using GetElem
class ArrayType (Cont : outParam Type) (Idx Elem : Type) extends GetElem Cont Idx Elem (λ _ _ => True)
I really want this instance:
instance : ArrayType {a : FloatArray // a.size = n} (Fin n) Float := ...
so I can write Float^(Fin n)
and get FloatArray
Tomas Skrivan (Apr 24 2023 at 16:13):
It looks like the change happened in 4544443. @Gabriel Ebner Any thoughts on this? Am I doing something bad/discouraged or was this an unintended consequence?
Reid Barton (Apr 24 2023 at 16:20):
Does turning off this synthInstance.checkSynthOrder
option help?
Yaël Dillies (Apr 24 2023 at 16:21):
Have you read https://leanprover.zulipchat.com/#narrow/stream/287929-mathlib4/topic/FunLike.20issues/near/345815614. Does using SemiOutParam
in places help?
Tomas Skrivan (Apr 24 2023 at 16:21):
I will give it a read!
Yaël Dillies (Apr 24 2023 at 16:22):
Disclaimer: I haven't understood the new system myself
Tomas Skrivan (Apr 24 2023 at 16:23):
A quick test, this does not work:
class ArrayType (T : semiOutParam Type) (I X : Type) extends GetElem T I X (λ _ _ => True)
but I have to read up on what semiOutParam
is actually doing
Tomas Skrivan (Apr 24 2023 at 16:25):
I see that the attribute infer_tc_goals_rl
disappeared. I'm assuming these changes have something to do with typeclass outparams that were causing some issues.
Tomas Skrivan (Apr 24 2023 at 16:30):
Reid Barton said:
Does turning off this
synthInstance.checkSynthOrder
option help?
Yes! This solves the problem.
But maybe I should rethink my code and have a specialized notation class.
Gabriel Ebner (Apr 24 2023 at 16:49):
The purpose of the check is to prevent [GenericArrayType Cont Idx Elem] [Monoid Elem]
from blowing up when you have an ArrayType (Array α) (Fin n) α
instance.
Gabriel Ebner (Apr 24 2023 at 16:51):
If you only have instances like the FloatArray one, then you should mark the Idx
and Elem
parameters (in ArrayType
) as semiOutParam
.
Gabriel Ebner (Apr 24 2023 at 16:55):
Although that instance will still complain about the n
parameter.
Gabriel Ebner (Apr 24 2023 at 16:55):
(deleted)
Tomas Skrivan (Apr 24 2023 at 17:44):
Gabriel Ebner said:
The purpose of the check is to prevent
[GenericArrayType Cont Idx Elem] [Monoid Elem]
from blowing up when you have anArrayType (Array α) (Fin n) α
instance.
I do have instances for algebraic structures over arrays and I remember running into problems like this quite often but I forgot how I solved it.
I should probably revise my typeclass hierarchy.
Yakov Pechersky (May 22 2023 at 03:25):
I am running into this when trying to define a seemingly simple Category:
universe v u
inductive RelHom {S : Type u} (r : S → S → Prop) (a b : S)
| ofRel : r a b → RelHom r a b
class IsRefl (α : Type u) (r : α → α → Prop) : Prop where
refl : ∀ a, r a a
class Quiver (V : Type u) where
Hom : V → V → Sort v
open Quiver (Hom)
instance RelQuiver (S : Type u) (r : S → S → Prop) : Quiver S where
Hom a b := RelHom r a b
class IsTrans (α : Type u) (r : α → α → Prop) : Prop where
trans : ∀ a b c, r a b → r b c → r a c
class CategoryStruct (obj : Type u) extends Quiver.{v + 1} obj : Type max u (v + 1) where
id : ∀ X : obj, Hom X X
-- cannot find synthesization order for instance instCategoryStruct with type
-- (S : Type u) → (r : S → S → Prop) → [inst : IsRefl S r] → CategoryStruct S
-- all remaining arguments have metavariables:
-- IsRefl S ?r
instance (S : Type u) (r : S → S → Prop) [IsRefl S r] : CategoryStruct S where
Hom a b := RelHom r a b
id a := .ofRel (IsRefl.refl a)
I can't tell what the issue with the IsRefl S r
here.
Kevin Buzzard (May 22 2023 at 05:32):
set_option synthInstance.checkSynthOrder false
solves it (see above)
Kevin Buzzard (May 22 2023 at 05:33):
Should something be an outParam?
Yakov Pechersky (May 22 2023 at 05:39):
It "solves" it, yes, but I don't know what exactly it's "solving" -- it removes the error, but turning off such an option makes me think it's hiding some other failure somewhere.
Gabriel Ebner (May 23 2023 at 00:05):
Yes, it solves it in the same way that nolint
sweeps issues under the rug.
Gabriel Ebner (May 23 2023 at 00:07):
The issue in your example is that the relation r
is completely undetermined. If you've an IsRefl S rel1
and and IsRefl S rel2
instance, then CategoryStruct S
might use either one of them (maybe even depending on the order of the imports in the file).
Gabriel Ebner (May 23 2023 at 00:08):
In this example, I'd probably add a def Rel (A : Type u) (r : A -> A -> Prop) := A
type alias and use that in the instance (i.e., CategoryStruct (Rel S r)
Yakov Pechersky (May 23 2023 at 00:21):
Why doesn't it complain about possibly overlapping instances at the RelQuiver decl, where r only factors into the body of the Quiver, not the type?
Gabriel Ebner (May 23 2023 at 00:34):
Oh, the RelQuiver
instance is also super problematic, as it will always apply and never work since it can't figure out the r
(and Lean will only notice this at the very end so this has the effect of disabling the other Quiver
instances..).
Gabriel Ebner (May 23 2023 at 00:34):
The reason why Lean doesn't print an error for that is because that check can be implemented as a linter in mathlib.
Last updated: Dec 20 2023 at 11:08 UTC