Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala 惯用的方法;撰写;使用猫的幺半群?_Scala_Functional Programming_Scala Cats_Monoids - Fatal编程技术网

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)
  )
}