Scala函数半群
我正在尝试将HaskellScala函数半群,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代码 导入猫半群
半群
转换为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的人。