[英]Semigroup with function in Scala
I'm trying to convert an Haskell Semigroup
to Scala. 我正在尝试将Haskell
Semigroup
转换为Scala。 The Haskell code works fine but I can't write it in Scala Haskell代码可以正常工作,但我无法在Scala中编写它
Haskell: Haskell:
import Data.Semigroup
newtype Combine a b = Combine { unCombine :: (a -> b) }
instance Semigroup b => Semigroup (Combine a b) where
Combine f <> Combine g = Combine (f <> g)
f = Combine $ \n -> Sum (n + 1)
g = Combine $ \n -> Sum (n - 1)
print (unCombine (f <> g) $ 0) -- Sum 0
print (unCombine (f <> g) $ 10) -- Sum 20
Scala code Scala代码
import cats.Semigroup
import cats.instances.all._
trait Combine[A, B] {
def unCombine(a: A): B
}
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
}
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] = (x,y) match {
// ???
}
}
In addition to the answer by @KartikSabharwal, because both Semigroup
and Combine
are functional interfaces, since Scala 2.12 you can define the specific case like this: 除了由@KartikSabharwal答案,因为这两个
Semigroup
和Combine
是功能接口,因为Scala的2.12可以定义具体情况是这样的:
implicit val mySemigroup: Semigroup[Combine[Int, Int]] =
(x, y) => a => x.unCombine(a) + y.unCombine(a)
And the generic case, which @KartikSabharwal has mentioned would look like this in Scala 2.12: @KartikSabharwal提到的通用案例在Scala 2.12中看起来像这样:
// Don't forget to NOT import `cats.instances.all._` together with this import
import cats.implicits._
implicit def combineSemigroup[A, B](
implicit ev: Semigroup[B]
): Semigroup[Combine[A, B]] =
(x, y) => a => x.unCombine(a) combine y.unCombine(a)
And like this in Scala 2.11: 像在Scala 2.11中这样:
import cats.implicits._
implicit def combineSemigroup[A, B](
implicit ev: Semigroup[B]
): Semigroup[Combine[A, B]] =
new Semigroup[Combine[A, B]] {
override def combine(x: Combine[A, B], y: Combine[A, B]): Combine[A, B] =
new Combine[A, B] {
override def unCombine(a: A): B = x.unCombine(a) combine y.unCombine(a)
}
}
Here's code that answers your specific question. 这是可以回答您特定问题的代码。
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)
}
}
Ideally I'd like to duplicate the Haskell code in spirit and implement something of the form 理想情况下,我想在本质上复制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))
}
But I don't know enough Scala to accomplish it. 但是我对Scala的了解还不够多。 I'll update the answer when I figure it out or someone else can come along and edit this answer/post a better one.
找出答案后,我将对其进行更新,否则其他人可以跟进并编辑此答案/发布更好的答案。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.