我想用猫来“组成”两个类人动物。如果存在已定义的Monoid[(A, A) => Int]
,那么我希望能够使用Monoid[Preference[A]]
的{{1}}和combine
方法来创建empty
。我在这里宽松地使用了“合成”一词,因为我不确定我要进行的转换是否准确地称为合成。
这是我目前的尝试...
Monoid[(A, A) => Int]
...这可以编译,但是我想知道是否有使用猫的惯用解决方案。
似乎应该可以以某种方式将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)
}
}
}
}
与Monoid[(A,A) => Int]
组合器组成,该组合器采用from
并返回f:(A, A) => Int
以创建Preference[A]
但我不知道该怎么做。
我看过这篇SO帖子,其中讨论了使用Monoid[Preference[A]]
组合器来编写类半体词,这不是我想要的。
答案 0 :(得分:1)
我不知道cats
中直接内置的任何内容。
似乎您在Preference[A]
和(A, A) => Int
之间具有同构,并且您只想将类半球形结构从(A, A) => Int
转移到Preference[A]
。可以一般地用任意类型A
和B
来表示:
def fromIsomorphicMonoid[A, B](
forward: A => B,
inverse: B => A
)(implicit aMon: Monoid[A]): Monoid[B] = new Monoid[B] {
def combine(b1: B, b2: B): B =
forward(aMon.combine(inverse(b1), inverse(b2)))
def empty: B = forward(aMon.empty)
}
使用此帮助程序方法,您在monoid
中的Preference
变为:
def monoid[A](implicit ev: Monoid[(A, A) => Int]): Monoid[Preference[A]] =
fromIsomorphicMonoid(
from,
(p: Preference[A]) => (x:A, y:A) => p.compare(x, y)
)
完整的可编译示例(没有任何依赖性):
trait Monoid[X] {
def empty: X
def combine(x: X, y: X): X
}
trait Order[A] {
def compare(a1: A, a2: A): Int
}
def fromIsomorphicMonoid[A, B](
forward: A => B,
inverse: B => A
)(implicit aMon: Monoid[A]): Monoid[B] = new Monoid[B] {
def combine(b1: B, b2: B): B =
forward(aMon.combine(inverse(b1), inverse(b2)))
def empty: B = forward(aMon.empty)
}
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]] = fromIsomorphicMonoid(
from,
(p: Preference[A]) => (x:A, y:A) => p.compare(x, y)
)
}