Вот код, который отвечает на ваш конкретный вопрос.
import cats.Semigroup
import cats.instances.all._
object Main extends App {
trait Combine[A, B] {
def unCombine(a: A): B
}
override def main(args: Array[String]): Unit = {
implicit val mySemigroup: Semigroup[Combine[Int, Int]] =
new Semigroup[Combine[Int, Int]] {
def combine(x: Combine[Int, Int], y: Combine[Int, Int]): Combine[Int, Int] =
new Combine[Int, Int] {
override def unCombine(n: Int): Int =
Semigroup[Int].combine(x.unCombine(n), y.unCombine(n))
}
}
val f = new Combine[Int, Int] {
override def unCombine(n: Int): Int = n + 1
}
val g = new Combine[Int, Int] {
override def unCombine(n: Int): Int = n - 1
}
val example = Semigroup[Combine[Int, Int]].combine(f, g).unCombine(10)
printf("%d\n", example)
}
}
В идеале Я бы хотел продублировать код Haskell по духу и реализовать что-то в форме
// 'a' can be any type
// Semigroup[b] must exist
implicit val mySemigroup: Semigroup[Combine[a, b]] =
def combine(x: Combine[a, b], y: Combine[a, b]): Combine[a, b] =
new Combine[a, b] {
override def unCombine(n: a): b =
Semigroup[b].combine(x.unCombine(n), y.unCombine(n))
}
Но я не знаю достаточно Scala, чтобы выполнить это.Я обновлю ответ, когда выясню, или кто-то другой может прийти и отредактировать этот ответ / опубликовать лучший.