I would like to "compose" two monoids using cats. If there exists a defined Monoid[(A, A) => Int]
, then I would like to be able to create a Monoid[Preference[A]]
using the combine
and empty
methods of the Monoid[(A, A) => Int]
. I am using the term "composing" loosely here because I am not sure that the transform I want to do is accurately called composition.
Here is my current attempt...
import cats._
import cats.implicits._
trait Preference[A] extends Order[A]
object Preference {
def from[A](f: (A, A) => Int): Preference[A] = {
new Preference[A] {
def compare(a1: A, a2: A): Int = {
f(a1, a2)
}
}
}
def monoid[A](implicit ev: Monoid[(A, A) => Int]): Monoid[Preference[A]] = {
new Monoid[Preference[A]] {
def combine(p1: Preference[A], p2: Preference[A]): Preference[A] = {
new Preference[A] {
def compare(a1: A, a2:A): Int = {
ev.combine(p1.compare, p2.compare)(a1, a2)
}
}
}
def empty: Preference[A] = {
from(ev.empty)
}
}
}
}
...this compiles but I would like to know if there is a more idiomatic solution available using cats.
Seems like it should be possible to somehow compose the Monoid[(A,A) => Int]
with the from
combinator that takes a f:(A, A) => Int
and returns a Preference[A]
to create a Monoid[Preference[A]]
but I can not figure out how to do it.
I have seen this SO post which discusses composing monoids using a product
combinator which is not what I want.