Zulip Chat Archive

Stream: lean4

Topic: CoeHTCT synthesis timing out with default args and coercions


Yakov Pechersky (Nov 20 2022 at 23:47):

As part of the mathlib4 port (mathlib4#549), I'm running into an CoeHTCT synthesis timeout. I've minimized away from any mathlib4 import. There seems to a complicated contribution to the timeout, where commenting out some of the instances, or remove default terms/proofs in some of the class definitions, prevents the timeout.

universe u

class One (α : Type u) where
  one : α

instance One.toOfNat1 {α} [One α] : OfNat α (nat_lit 1) where
  ofNat := One α.1

variable {G : Type _}

class Inv (α : Type u) where
  inv : α  α

postfix:max "⁻¹" => Inv.inv

class Semigroup (G : Type u) extends Mul G where
  mul_assoc :  a b c : G, a * b * c = a * (b * c)

class CommSemigroup (G : Type u) extends Semigroup G where
  mul_comm :  a b : G, a * b = b * a

class MulOneClass (M : Type u) extends One M, Mul M where
  one_mul :  a : M, 1 * a = a
  mul_one :  a : M, a * 1 = a

section

variable {M : Type u}

def npowRec [One M] [Mul M] : Nat  M  M
  | 0, _ => 1
  | n + 1, a => a * npowRec n a

end

class Monoid (M : Type u) extends Semigroup M, MulOneClass M where
  npow : Nat  M  M := npowRec
  npow_zero' :  x, npow 0 x = 1 := by intros; rfl -- can comment this out to not timeout

@[default_instance high] instance Monoid.Pow {M : Type _} [Monoid M] : Pow M Nat :=
  fun x n => Monoid.npow n x

class CommMonoid (M : Type u) extends Monoid M, CommSemigroup M

class DivInvMonoid (G : Type u) extends Monoid G, Inv G, Div G where
  div a b := a * b⁻¹ -- or remove this and the `extends Div G` to not timeout

class Group (G : Type u) extends DivInvMonoid G where
  mul_left_inv :  a : G, a⁻¹ * a = 1

class CommGroup (G : Type u) extends Group G, CommMonoid G

structure Units (α : Type u) [Monoid α] where
  val : α

-- comment out any of the instances below to have `mul_pow'` not time out
instance (priority := low) [Monoid α] : Coe (Units α) α :=
  Units.val

instance [Monoid α] : Group (Units α) where
  one := One.one
  mul u₁ u₂ := u₁.val * u₂.val
  inv := fun u => u.1
  one_mul u := sorry
  mul_one u := sorry
  mul_left_inv := sorry
  mul_assoc := sorry

instance {α} [CommMonoid α] : CommGroup (Units α) where
  one := One.one
  mul u₁ u₂ := u₁.val * u₂.val
  inv := fun u => u.1
  one_mul u := sorry
  mul_one u := sorry
  mul_left_inv := sorry
  mul_assoc := sorry
  mul_comm := sorry

variable {M : Type _}

theorem mul_pow' [CommMonoid M] (a b : M) (n : Nat) : (a * b) ^ n = a ^ n * b ^ n := sorry -- this times out
theorem mul_pow'' [CommMonoid M] (a b : M) (n : Nat) : HPow.hPow (a * b) n = HPow.hPow a n * HPow.hPow b n := sorry -- this doesn't time out

Gabriel Ebner (Nov 21 2022 at 00:31):

Coe (Units α) α must not be an instance.

Gabriel Ebner (Nov 21 2022 at 00:32):

This leads to nontermination, see also https://leanprover.zulipchat.com/#narrow/stream/270676-lean4/topic/Gory.20details.20of.20.60coe.60/near/311183132

Gabriel Ebner (Nov 21 2022 at 00:32):

It could be CoeHead or CoeTail.

Yakov Pechersky (Nov 21 2022 at 00:53):

Makes sense -- why does commenting out the npow proof fix it?

Kevin Buzzard (Nov 21 2022 at 07:22):

I don't get this at all. We can't have a coercion from the units of a monoid to the monoid? How am I supposed to know if this is a head or a tail?

Mario Carneiro (Nov 21 2022 at 08:27):

we used to have a convention that coes of the form Coe (T A) A should be head coes and Coe A (T A) should be tail coes, or was it vice versa?

Mario Carneiro (Nov 21 2022 at 08:28):

I'm guessing we want it to be a head coe

Mario Carneiro (Nov 21 2022 at 08:30):

It won't really matter for most purposes unless you start chaining coercions, like if you have an element in {x : Units Nat // p x} and you want an Int

Kevin Buzzard (Nov 21 2022 at 09:09):

Right! I don't see why I shouldn't want that in general. How would one do that example in lean 4?

Mario Carneiro (Nov 21 2022 at 09:12):

You wouldn't

Mario Carneiro (Nov 21 2022 at 09:13):

I don't think it's possible with the current setup of coercions, since there is at most one CoeHead or CoeTail

Mario Carneiro (Nov 21 2022 at 09:15):

you would need something like CoeHead? CoeOut* CoeIn* CoeTail? where CoeOut : A -> outParam B and CoeIn : outParam A -> B

Mario Carneiro (Nov 21 2022 at 09:16):

currently we only have CoeIn (that's Coe)

Mario Carneiro (Nov 21 2022 at 09:16):

You would need CoeOut as well in order to chain coes like the Units one

Mario Carneiro (Nov 21 2022 at 09:19):

but also, chained coercions were a big headache in lean 3 and I would not be surprised if we essentially only use chained coercions in a very limited way in mathlib because of this

Mario Carneiro (Nov 21 2022 at 09:21):

note that you can always insert type ascriptions to force multiple coercion in case lean won't do it in one go

Kevin Buzzard (Nov 21 2022 at 09:59):

Ok so if multiple type ascriptions still work this is fine


Last updated: Dec 20 2023 at 11:08 UTC