class OpAssoc (op : α → α → α) : Prop where
  protected op_assoc (x y z) : op (op x y) z = op x (op y z)

abbrev op_assoc (op : α → α → α) [self : OpAssoc op] := self.op_assoc

structure SemigroupSig (α) where
  op : α → α → α

structure SemiringSig (α) where
  add : α → α → α
  mul : α → α → α

def SemiringSig.toAddSemigroupSig (s : SemiringSig α) : SemigroupSig α where
  op := s.add

def SemiringSig.toMulSemigroupSig (s : SemiringSig α) : SemigroupSig α where
  op := s.mul

unif_hint (s : SemiringSig α) (t : SemigroupSig α) where
  t =?= s.toAddSemigroupSig ⊢ t.op =?= s.add

unif_hint (s : SemiringSig α) (t : SemigroupSig α) where
  t =?= s.toMulSemigroupSig ⊢ t.op =?= s.mul

class Semigroup (s : SemigroupSig α) : Prop where
  protected op_assoc (x y z) : s.op (s.op x y) z = s.op x (s.op y z)

instance Semirgoup.toOpAssoc (s : SemigroupSig α) [Semigroup s] : OpAssoc (no_index s.op) := ⟨Semigroup.op_assoc⟩

class Semiring (s : SemiringSig α) : Prop where
  protected add_assoc (x y z) : s.add (s.add x y) z = s.add x (s.add y z)
  protected mul_assoc (x y z) : s.mul (s.mul x y) z = s.mul x (s.mul y z)

instance Semiring.toAddSemigroup (s : SemiringSig α) [Semiring s] : Semigroup (no_index s.toAddSemigroupSig) where
  op_assoc := Semiring.add_assoc

instance Semiring.toMulSemigroup (s : SemiringSig α) [Semiring s] : Semigroup (no_index s.toMulSemigroupSig) where
  op_assoc := Semiring.mul_assoc

section Test
variable (s : SemiringSig α) [Semiring s]

local infix:70 " ⋆ " => s.mul

example (w x y z : α) : (w ⋆ x) ⋆ (y ⋆ z) = w ⋆ ((x ⋆ y) ⋆ z) := by
  repeat rw [op_assoc (.⋆.)]

end Test
