/-- **Every list algebra is a monoid.** Multiply by evaluating two-element lists,
`x * y = act [x, y]`, and take `1 = act []`. The monoid laws follow from the algebra laws:
for example `(x * y) * z = act [act [x, y], act [z]] = act [x, y, z]`, and likewise
`x * (y * z) = act [x, y, z]`. -/
@[instance_reducible]
def toMonoid (A : ListAlgebra X) : Monoid X where
mul x y := A.act [x, y]
one := A.act []
mul_assoc x y z := by
show A.act [A.act [x, y], z] = A.act [x, A.act [y, z]]
have h₁ : A.act [A.act [x, y], z] = A.act [x, y, z] := by
calc A.act [A.act [x, y], z] = A.act ([[x, y], [z]].map A.act) := by simp [A.unit]
_ = A.act [x, y, z] := by rw [A.assoc]; simp
have h₂ : A.act [x, A.act [y, z]] = A.act [x, y, z] := by
calc A.act [x, A.act [y, z]] = A.act ([[x], [y, z]].map A.act) := by simp [A.unit]
_ = A.act [x, y, z] := by rw [A.assoc]; simp
rw [h₁, h₂]
one_mul x := by
show A.act [A.act [], x] = x
calc A.act [A.act [], x] = A.act ([[], [x]].map A.act) := by simp [A.unit]
_ = x := by rw [A.assoc]; simp [A.unit]
mul_one x := by
show A.act [x, A.act []] = x
calc A.act [x, A.act []] = A.act ([[x], []].map A.act) := by simp [A.unit]
_ = x := by rw [A.assoc]; simp [A.unit]