diff --git a/src/main/scala/algebra/Monoid.scala b/src/main/scala/algebra/Monoid.scala
index 12656457e2a67602a5a4afe3e23a3599177e35c0..276966e07ca72284d337c95470a2e7ef6449f7f0 100644
--- a/src/main/scala/algebra/Monoid.scala
+++ b/src/main/scala/algebra/Monoid.scala
@@ -1,5 +1,8 @@
 package algebra
 
 trait Monoid[A]:
-  def op(a1: A, a2: A): A
+  def combine(a1: A, a2: A): A
   def zero: A
+
+  extension (a1: A)
+    def |+| (a2: A) = combine(a1, a2)
diff --git a/src/main/scala/algebra/Monoids.scala b/src/main/scala/algebra/Monoids.scala
index 7639a43e10284b35e35ecce3fffce2197428c65b..a7d5d5bb431fa76064a218fa6f42bc3719da677c 100644
--- a/src/main/scala/algebra/Monoids.scala
+++ b/src/main/scala/algebra/Monoids.scala
@@ -1,34 +1,33 @@
 package algebra
 
-object Monoids:
-  def intAddition: Monoid[Int] = new Monoid[Int] {
-    def zero = ???
-    def op(a: Int, b: Int): Int = ???
-  }
+def intAddition: Monoid[Int] = new Monoid[Int] {
+  def zero = ???
+  def combine(a: Int, b: Int): Int = ???
+}
 
-  def intMultiplication: Monoid[Int] = ???
+def intMultiplication: Monoid[Int] = ???
 
-  def booleanOr: Monoid[Boolean] = ???
+def booleanOr: Monoid[Boolean] = ???
 
-  def booleanAnd: Monoid[Boolean] = ???
+def booleanAnd: Monoid[Boolean] = ???
 
-  def optionMonoid[A]: Monoid[Option[A]] = ???
+def optionMonoid[A]: Monoid[Option[A]] = ???
 
-  def endoMonoid[A]: Monoid[A => A] = ???
+def endoMonoid[A]: Monoid[A => A] = ???
 
-  def foldMap[A, B](as: List[A], m: Monoid[B])(f: A => B): B = ???
+def foldMap[A, B](as: List[A], m: Monoid[B])(f: A => B): B = ???
 
-  def foldMapBalanced[A, B](as: IndexedSeq[A], m: Monoid[B])(f: A => B): B = ???
+def foldMapBalanced[A, B](as: IndexedSeq[A], m: Monoid[B])(f: A => B): B = ???
 
-  def mapMergeMonoid[K,V](V: Monoid[V]): Monoid[Map[K, V]] =
-    new Monoid[Map[K, V]] {
-      def zero = Map[K,V]()
-      def op(a: Map[K, V], b: Map[K, V]) =
-        (a.keySet ++ b.keySet).foldLeft(zero) { (acc,k) =>
-          acc + (k ->
-            V.op(a.getOrElse(k, V.zero), b.getOrElse(k, V.zero)))
-        }
-    }
+def mapMergeMonoid[K,V](V: Monoid[V]): Monoid[Map[K, V]] =
+  new Monoid[Map[K, V]] {
+    def zero = Map[K,V]()
+    def combine(a: Map[K, V], b: Map[K, V]) =
+      (a.keySet ++ b.keySet).foldLeft(zero) { (acc,k) =>
+        acc + (k ->
+          V.combine(a.getOrElse(k, V.zero), b.getOrElse(k, V.zero)))
+      }
+  }
 
-  def bag[A](as: IndexedSeq[A]): Map[A, Int] = ???
+def bag[A](as: IndexedSeq[A]): Map[A, Int] = ???
 
diff --git a/src/main/scala/readerwriter/internal/Writer.scala b/src/main/scala/readerwriter/internal/Writer.scala
index 0f824bde95e183bc6f799ac346c2923d892fa618..7dc81fa093c92f24203c61ceaab5351787d78a3b 100644
--- a/src/main/scala/readerwriter/internal/Writer.scala
+++ b/src/main/scala/readerwriter/internal/Writer.scala
@@ -8,7 +8,7 @@ final case class Writer[L, A](v: (L, A))
 object Writer:
   implicit def listMonoid[A]: Monoid[List[A]] = new Monoid[List[A]] {
     def zero: List[Nothing] = List.empty
-    def op(l1: List[A], l2: List[A]): List[A] = l1 ++ l2
+    def combine(l1: List[A], l2: List[A]): List[A] = l1 ++ l2
   }
 
   def tell[L](l: L): Writer[L, Unit] = Writer((l, ()))
@@ -16,9 +16,9 @@ object Writer:
   given writerMonad[L: Monoid]: Monad[[a] =>> Writer[L, a]] with
     override def flatMap[A, B](fa: Writer[L, A])(f: A => Writer[L, B]): Writer[L, B] =
       val next = f(fa.v._2)
-      Writer((implicitly[Monoid[L]].op(fa.v._1, next.v._1), next.v._2))
+      Writer((implicitly[Monoid[L]].combine(fa.v._1, next.v._1), next.v._2))
 
     def pure[A](a: A): Writer[L, A] = Writer((implicitly[Monoid[L]].zero, a))
     override def map2[A, B, C](fa: Writer[L, A], fb: Writer[L, B])(f: (A, B) => C): Writer[L, C] =
-      Writer((implicitly[Monoid[L]].op(fa.v._1, fb.v._1), f(fa.v._2, fb.v._2)))
+      Writer((implicitly[Monoid[L]].combine(fa.v._1, fb.v._1), f(fa.v._2, fb.v._2)))
     override def map[A, B](fa: Writer[L, A])(f: A => B): Writer[L, B] = Writer((fa.v._1, f(fa.v._2)))