Zulip Chat Archive
Stream: general
Topic: Instance parameters depending on `out_params`
Anne Baanen (Jan 03 2022 at 11:14):
While troubleshooting #11128, I discovered a principle of typeclasses that was kind of surprising to me: if a class takes an instance parameter, and that instance parameter depends on an out_param
, sometimes instance search gets blocked:
prelude
import init.core
class semiring (G : Type*) := (one : G)
instance : semiring nat := ⟨1⟩
namespace erroring
class add_monoid_hom_class (F : Type*) (H : out_param Type*) [semiring H] :=
(coe : F → nat → H)
(ext_nat : ∀ (f g : F), coe f 1 = coe g 1 → f = g)
open add_monoid_hom_class
class semiring_hom_class (F : Type*) (H : out_param Type*) [semiring H]
extends add_monoid_hom_class F H :=
(map_one : ∀ (f : F), coe f 1 = semiring.one)
lemma semiring_hom_class.ext_nat {F : Type*} {H : out_param Type*} [semiring H]
[semiring_hom_class F H] (f g : F) : f = g :=
add_monoid_hom_class.ext_nat f g $
(semiring_hom_class.map_one f).trans (semiring_hom_class.map_one g).symm
-- error: can't synthesize type `H`
-- no attempt is made to infer `add_monoid_hom_class`
end erroring
The correct solution appears to make everything that depends on an out_param
also an out_param
:
namespace working
class add_monoid_hom_class (F : Type*) (H : out_param Type*) [out_param $ semiring H] :=
(coe : F → nat → H)
(ext_nat : ∀ (f g : F), coe f 1 = coe g 1 → f = g)
open add_monoid_hom_class
class semiring_hom_class (F : Type*) (H : out_param Type*) [out_param $ semiring H]
extends add_monoid_hom_class F H :=
(map_one : ∀ (f : F), coe f 1 = semiring.one)
lemma semiring_hom_class.ext_nat {F : Type*} {H : out_param Type*} [semiring H]
[semiring_hom_class F H] (f g : F) : f = g :=
add_monoid_hom_class.ext_nat f g $
(semiring_hom_class.map_one f).trans (semiring_hom_class.map_one g).symm
end working
Does the smarter order of elaboration in Lean 4 fix this?
Gabriel Ebner (Jan 03 2022 at 11:21):
This has nothing to do with the elaboration order.
Gabriel Ebner (Jan 03 2022 at 11:23):
What happens when you mark a type class argument as out_param
is that Lean will preprocess type class queries for that class as follows:
add_monoid_hom_class (A ...) (B...)
is rewritten to add_monoid_hom_class (A ...) ?H
(i.e., every out_param is replaced by a metavariable).
Gabriel Ebner (Jan 03 2022 at 11:24):
Note: this only happens for the top-level query. No preprocessing happens during search. If you have instance [add_monoid_hom_class A B] : blah
then B
is not replaced by a metavariable when the instance is applied.
Gabriel Ebner (Jan 03 2022 at 11:29):
Looking at your example more closely, marking the instances as out_param as well is actually supposed to be done automatically:
Type class parameters can be annotated with out_param annotations.
Given (C a_1 ... a_n), we replace a_i with a temporary metavariable ?x_i IF
Case 1
a_i is an out_param
ORCase 2
a_i depends on a_j for j < i, and a_j was replaced with a temporary metavariable ?x_j.
This case is needed to make sure the new C-application is type correct.
Anne Baanen (Jan 03 2022 at 13:21):
I now have the precise diagnosis: elaborator::synthesize_type_class_instances_step
skips instances if elaborator::ready_to_synthesize
indicates they have metavariables that are not covered by out_param
s. However, it doesn't count dependencies of out_param
s. (Note that preprocess_class
is called by the elaborator only after the elaborator decides to call mk_instance
, i.e. ready_to_synthesize
returns true. So I'd say this is kind of an elaboration order issue.)
Anne Baanen (Jan 03 2022 at 13:25):
Unfortunately, copying the logic from type_context_old::preprocess_class
to elaborator::ready_to_synthesize
is not so easy, since preprocess_class
uses the metavariables it inserts for out_param
s to determine the other parameters that have a dependency.
Anne Baanen (Jan 03 2022 at 14:41):
Alright, I think I have something that works correctly. After the version with more documentation (re-)compiles I'll run the test suite with an assert
that the new non-mutating check does the same as the previous one.
Anne Baanen (Jan 03 2022 at 15:44):
Last updated: Dec 20 2023 at 11:08 UTC