Zulip Chat Archive

Stream: general

Topic: type class inference issues


Floris van Doorn (Feb 15 2019 at 15:57):

I have been struggling with type class inference lately. The two main issues are
(1) The error maximum class-instance resolution depth has been reached
(2) In some cases (which are hard to reproduce in minimal examples) I get incredibly long elaboration times (10-30 seconds for a single definition), and I suspect this is completely caused by type class inference (the eventual error I often get is that the type-class max depth is reached).

Problem 1 can be easily solved by setting the class.instance_max_depth option higher. Problem 2 makes this solution for problem 1 not that attractive, if type class inference then takes even longer.

I have some concrete and some open-ended questions:
Q.1 What does instance_max_depth exactly mean? Does it mean the depth/height of the search tree, or the total number of instances in the solution? For example, in the following example I have to set the depth to 125, with 124 it fails:

import ring_theory.algebra linear_algebra.tensor_product

variables {R : Type*} [comm_ring R]
variables {M : Type*} {N : Type*} [ring M] [ring N]
variables [algebra R M] [algebra R N]

local notation M ` ⊗[`:100 R `] ` N:100 := tensor_product R M N

namespace tensor_product
set_option class.instance_max_depth 125

protected def mul : M ⊗[R] N →ₗ[R] M ⊗[R] N →ₗ[R] M ⊗[R] N :=
begin
  refine tensor_product.lift ⟨λ m, ⟨λ n, _, _, _⟩, _, _⟩,
  all_goals { sorry }
end

Q.2 Does the option trace.class_instances show the complete trace or does Lean/VSCode truncate the trace somewhere? In traces where I get the max-depth reached error, the highest depth I can find is typically (11) or (12)
Q.3 In the trace, I see the same type class search over and over again (in a single definition). Is the caching of type class instances failing me, or is something else going on?
Q.4 What are type-class best practices? Do I want to add instances to short-circuit the type class inference? For example, in the example above, if I add the following local instances I don't have to increase the max depth at all:

protected def add_comm_group' : add_comm_group (M ⊗[R] N) := by apply_instance
protected def module' : module R (M ⊗[R] N) := by apply_instance
local attribute [instance, priority 2000] tensor_product.add_comm_group' tensor_product.module'
protected def lmap_add_comm_group : add_comm_group (M ⊗[R] N →ₗ[R] M ⊗[R] N) := by apply_instance
protected def lmap_module : module R (M ⊗[R] N →ₗ[R] M ⊗[R] N) := by apply_instance
local attribute [instance, priority 2000]
  tensor_product.lmap_add_comm_group tensor_product.lmap_module

Are there other tips/tricks to keep type-class inference happy/under control?

Floris van Doorn (Feb 15 2019 at 22:06):

PS: The reason for the example in Q.1 is that I'm surprised I would need to go to depth 100+.

Floris van Doorn (Feb 15 2019 at 22:08):

I just had another problem with type class inference.
I have an instance (with pp.all true):

_inst_3 : @is_ring_hom.{u_1 u_2} α β (@comm_ring.to_ring.{u_1} α _inst_1) (@comm_ring.to_ring.{u_2} β _inst_2) f

But the trace shows that this instance does not unify with its own type, even with pp.all true.

[class_instances] (0) ?x_9 : @is_ring_hom.{u_1 u_2} α β (@comm_ring.to_ring.{u_1} α _inst_1) (@comm_ring.to_ring.{u_2} β _inst_2) f := _inst_3
failed is_def_eq

The error occurs here:
https://github.com/fpvandoorn/formalabstracts/blob/is_ring_hom/src/ring_theory/basic.lean#L28

Eric Rodriguez (Mar 28 2022 at 22:18):

import algebra.order.ring

def foo (α) [has_lt α] [decidable_rel ((<) : α  α  Prop)] := 123

example {R} [linear_ordered_semiring R] := foo R --error

example {R} [h : linear_ordered_semiring R] :=
begin
  refine @foo R _ (show _, from _),
  exact (infer_instance : linear_order R).10,
end

what the hell is going on here?! it doesn't seem to be a diamond

Eric Wieser (Mar 28 2022 at 22:20):

(I never even considered that numeric dot notation supported double digits)

Eric Wieser (Mar 28 2022 at 22:20):

What's the error message?

Eric Rodriguez (Mar 28 2022 at 22:22):

it just cannot find the instance

Eric Rodriguez (Mar 28 2022 at 22:24):

it seens that linear_ordered_semiring.decidable_lt isn't an instance, but the linear_order version is and ther'es also clearly a linear_order instance, so it should be able to find it

Anne Baanen (Mar 29 2022 at 09:56):

If I enable trace.class_instances, then first of all it looks like linear_order.decidable_lt is not considered an instance. So I add that attribute and get the following trace:

[class_instances] (0) ?x_0 a b : decidable (a < b) := @linear_order.decidable_lt (?x_1 a b) (?x_2 a b) (?x_3 a b) (?x_4 a b)
failed is_def_eq
...

Anne Baanen (Mar 29 2022 at 09:59):

Looks like it's struggling with the problem:

@preorder.to_has_lt R
  (@partial_order.to_preorder R
     (@ordered_cancel_add_comm_monoid.to_partial_order R
        (@ordered_semiring.to_ordered_cancel_add_comm_monoid R (@linear_ordered_semiring.to_ordered_semiring R h)))) =?= @preorder.to_has_lt (?x_1 a b)
  (@partial_order.to_preorder (?x_1 a b)
     (@partial_order.mk (?x_1 a b) (@linear_order.le (?x_1 a b) (?x_2 a b)) (@linear_order.lt (?x_1 a b) (?x_2 a b)) _ _
        _
        _))

Anne Baanen (Mar 29 2022 at 10:02):

?x_2 a b should be inferred as the linear_order instance deriving from h : linear_ordered_semiring R, but apparently it's just being treated as opaque and never inferred.

Anne Baanen (Mar 29 2022 at 10:03):

Maybe this is the "pi instance bug" we've seen before with finsupp?


Last updated: Dec 20 2023 at 11:08 UTC