Scala函数半群

Scala函数半群,scala,haskell,functional-programming,typeclass,semigroup,Scala,Haskell,Functional Programming,Typeclass,Semigroup,我正在尝试将Haskell半群转换为Scala。Haskell代码运行良好,但我不能用Scala编写它 Haskell: 导入数据半群 newtype Combine a b=Combine{unCombine::(a->b)} 实例半群b=>半群(组合a b),其中 联合收割机f联合收割机g=联合收割机(f g) f=组合$\n->总和(n+1) g=组合$\n->总和(n-1) 打印(取消组合(f g)$0)--总和0 打印(取消组合(f g)$10--总计20 Scala代码 导入猫半群

我正在尝试将Haskell
半群
转换为Scala。Haskell代码运行良好,但我不能用Scala编写它

Haskell:

导入数据半群
newtype Combine a b=Combine{unCombine::(a->b)}
实例半群b=>半群(组合a b),其中
联合收割机f联合收割机g=联合收割机(f g)
f=组合$\n->总和(n+1)
g=组合$\n->总和(n-1)
打印(取消组合(f g)$0)--总和0
打印(取消组合(f g)$10--总计20
Scala代码

导入猫半群 导入cats.instances.all_ 性状组合[A,B]{ def取消组合(a:a):B } val f=新联合收割机[Int,Int]{ 覆盖def取消组合(n:Int):Int=n+1 } val g=新联合收割机[Int,Int]{ 覆盖def取消组合(n:Int):Int=n-1 } 隐式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)匹配{ // ??? } }
以下是回答您具体问题的代码

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来完成它。当我找到答案时,我会更新答案,或者其他人可以过来编辑这个答案/发布一个更好的答案。

以下是回答您特定问题的代码

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来完成它。当我找到答案后,我会更新答案,或者其他人可以过来编辑这个答案/发布一个更好的答案。

除了@KartikSabharwal的答案之外,因为
半组
组合
都是功能接口,因为Scala 2.12可以定义如下特定情况:

implicit val mySemigroup: Semigroup[Combine[Int, Int]] =
  (x, y) => a => x.unCombine(a) + y.unCombine(a)
@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)
就像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)
      }
  }

除了@KartikSabharwal的回答之外,因为
半组
组合
都是功能接口,因为Scala 2.12可以这样定义特定情况:

implicit val mySemigroup: Semigroup[Combine[Int, Int]] =
  (x, y) => a => x.unCombine(a) + y.unCombine(a)
@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)
就像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)
      }
  }

在Haskell中,Combine(fg)
相当于有意义的
Combine(\x->fxgx)
。也许你可以用在Scala?原谅我;我对斯卡拉知之甚少。但在我看来,您在翻译中丢失了Haskell
实例
声明的
半群b=>
部分。具体来说,您的
隐式val mySemigroup
不接受任何论据,这从表面上看似乎是可疑的;它需要知道存储在
Combine
值中的函数的编码域在某种程度上是一个
半群。也许这就是给你带来麻烦的部分原因?请原谅我,我不认识Haskell,你能解释一下Haskell代码在做什么吗?Haskell代码首先定义了一个名为
combinab
的数据类型。任何类型为
combinab
的值都是
a->b
类型函数的包装器。包装函数的“getter方法”是
取消组合
。然后,代码使类型
组合为b
类型类
半组的实例。就像在代数组中一样,这涉及到对该类型的值定义关联运算符
()
。这里,
Combine f Combine g=Combine(f g)
要求
f
g
具有
a->b
类型,其中
b
也实现了
半群
fg
就像
\n->(fn)(gn)
我想,如果你用英语解释你想做什么,你会有更好的机会更快得到一个好答案。通过使用haskell来描述它,你排除了大部分观众——即说英语和scala但不说haskell的人。在haskell中,
Combine(f g)
相当于有意义的
Combine(\x->f x g x)
。也许你可以用在Scala?原谅我;我对斯卡拉知之甚少。但在我看来,您在翻译中丢失了Haskell
实例
声明的
半群b=>
部分。具体来说,您的
隐式val mySemigroup
不接受任何论据,这从表面上看似乎是可疑的;它需要知道存储在
Combine
值中的函数的编码域在某种程度上是一个
半群。也许这就是给你带来麻烦的部分原因?请原谅我,我不认识Haskell,你能解释一下Haskell代码在做什么吗?Haskell代码首先定义了一个名为
combinab
的数据类型。任何类型为
combinab
的值都是
a->b
类型函数的包装器。包装函数的“getter方法”是
取消组合
。然后,代码使类型
组合为b
类型类
半组的实例。就像在代数组中一样,这涉及到对该类型的值定义关联运算符
()
。这里,
Combine f Combine g=Combine(f g)
要求
f
g
具有
a->b
类型,其中
b
也实现了
半群
fg
就像
\n->(fn)(gn)
我想,如果你用英语解释你想做什么,你会有更好的机会更快得到一个好答案。用haskell来描述它,你就排除了大部分观众,也就是说英语和scala,但不是haskell的人。