Scala 惯用的方法;撰写;使用猫的幺半群?
我想用猫“组成”两个幺半群。如果存在已定义的Scala 惯用的方法;撰写;使用猫的幺半群?,scala,functional-programming,scala-cats,monoids,Scala,Functional Programming,Scala Cats,Monoids,我想用猫“组成”两个幺半群。如果存在已定义的Monoid[(a,a)=>Int],那么我希望能够使用Monoid[(a,a)=>Int]的combine和empty方法创建Monoid[Preference[a]]。我在这里松散地使用术语“合成”,因为我不确定我要做的转换是否准确地称为合成 这是我目前的尝试 import cats._ import cats.implicits._ trait Preference[A] extends Order[A] object Preferenc
Monoid[(a,a)=>Int]
,那么我希望能够使用Monoid[(a,a)=>Int]
的combine
和empty
方法创建Monoid[Preference[a]]
。我在这里松散地使用术语“合成”,因为我不确定我要做的转换是否准确地称为合成
这是我目前的尝试
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)
}
}
}
}
…这是可以编译的,但我想知道是否有一种更惯用的解决方案可以使用CAT
似乎应该可以用f:(A,A)组合来组合Monoid[(A,A)=>Int]
并返回Preference[A]
创建Monoid[Preference[A]]
但我无法确定如何进行
我看过这篇文章,它讨论了使用产品
组合器组合幺半群,这不是我想要的。我不知道直接内置在猫
中的任何东西
似乎在偏好[A]
和(A,A)=>Int
之间有一个同构,您只需要将幺半群结构从(A,A)=>Int
转移到偏好[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)
}
使用此帮助器方法,首选项中的幺半群
将变为:
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)
)
}