我正在继续研究Functional Programming in 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)
}
}
接下来,整数乘法monoid。
val intMultiplication = new Monoid[Int] {
def op(a1: Int, a2: Int) = a1 * a2
val zero = 1
}
最后,这个monoid简单地连接了两个字符串。
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(...)
惯用语吗?也许有一种更清晰的方式来编写这段代码?
答案 0 :(得分: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 lib。