2

我将继续从事Scala文本练习中的函数式编程。

下面的函数 ,productMonoid组成了两个幺半群。

//@author - pchiusano
def productMonoid[A, B](A: Monoid[A], B: Monoid[B]): Monoid[(A, B)] = {
    new Monoid[(A, B)] {
        def op(x: (A,B), y: (A,B) ) = (A.op(x._1, y._1) , B.op(x._2, y._2))
        val zero = (A.zero, B.zero)
    }
}

接下来是整数乘法幺半群。

val intMultiplication = new Monoid[Int] {
    def op(a1: Int, a2: Int) = a1 * a2
    val zero = 1
}

最后,这个幺半群只是连接两个字符串。

val concatenate = new Monoid[String] {
    def op(a1: String, a2: String) = a1 + a2
    val zero = ""
}

最后,我调用测试代码来验证productMonoid的功能。

def main(args: Array[String]) = {
    val x = (100, "hello")
    val y = (200, "world")

    val result: (Int, String) = productMonoid(intMultiplication, concatenate).op(x,y)
    println("result: " + result)
    assert(result._1 == 20000)
    assert(result._2 == "helloworld")
}

我的电话是productMonoid(...)惯用的吗?也许有一种更简洁的方法来编写这段代码?

4

1 回答 1

4

Imho Monoid 需要定义为 Type Class

trait Monoid[T] {
  def op(x: T, y: T): T
  def zero: T
}

并添加一些语法扩展以便于使用:

trait MonoidSyntax[T] {
  def |+|(y: T): T
  def zero: T
}

implicit def toMonoidSyntax[A: Monoid](x: A) = new MonoidSyntax[A] {
  def |+|(y: A) = implicitly[Monoid[A]].op(x, y)
  def zero = implicitly[Monoid[A]].zero
}

那么类型类实例将被定义为:

implicit val intMultiplication = new Monoid[Int] {
  def op(a1: Int, a2: Int) = a1 * a2
  val zero = 1
}

implicit val concatenate = new Monoid[String] {
  def op(a1: String, a2: String) = a1 + a2
  val zero = ""
}

和产品 Monoid 实例:

//@author - pchiusano
def productMonoid[A, B](A: Monoid[A], B: Monoid[B]): Monoid[(A, B)] = {
  new Monoid[(A, B)] {
    def op(x: (A,B), y: (A,B) ) = (A.op(x._1, y._1) , B.op(x._2, y._2))
    val zero = (A.zero, B.zero)
  }
}

// instance of tuple Monoid (A, B) for any A : Monoid, B : Monoid
implicit def productM[A: Monoid, B: Monoid] =
  productMonoid(implicitly[Monoid[A]], implicitly[Monoid[B]])

毕竟你的代码看起来像:

val x = (100, "hello")
val y = (200, "world")
val result = x |+| y

println("result: " + result)
assert(result._1 == 20000)
assert(result._2 == "helloworld")

最后,您不需要使用 monoids 编写代码。只需使用Scalaz库。

于 2013-11-14T06:17:58.903 回答