2

使用 Scalaz 7,我们可以得到幺半群积的零:

scala> mzero[(Int, String)]
res13: (Int, String) = (0,"")

有没有一种更简单的方法可以为字段为幺半群的案例类获取零?理想情况下,不需要重复字段的类型 à la:

scala> case class Foo(x: Int, y: String)
defined class Foo
scala> (Foo.apply _).tupled(mzero[(Int, String)])
res15: Foo = Foo(0,)
4

2 回答 2

6

即使在 Shapeless 中,您也需要一些样板文件,如下所示:

implicit def fooIso = Iso.hlist(Foo.apply _, Foo.unapply _)

我们可以在 Scalaz 7 中做类似的事情(虽然不那么优雅)。首先对于一些通用机械:

import scalaz._, Scalaz._, Isomorphism._

case class MonoidFromIsorphism[F, G](iso: F <=> G)(
  implicit val G: Monoid[G]
) extends IsomorphismMonoid[F, G]

现在我们可以写:

case class Foo(x: Int, y: String)

implicit object fooMonoid extends MonoidFromIsorphism(
  new IsoSet[Foo, (Int, String)] {
    def to = (Foo.unapply _) andThen (_.get)
    def from = (Foo.apply _).tupled
  }
)

哪个有效:

scala> mzero[Foo]
res0: Foo = Foo(0,)

这种方法仍然需要你重复类型,它并不比Foo手动写出实例更简洁(实际上,如果你计算MonoidFromIsomorphism定义,它就不那么简洁了,但对我来说,这感觉就像是真正应该做的方便的事情在图书馆)。

缺少的是HList-tuple 同构,它允许我们编写一个简单的Foo-HList同构,就像在 Shapeless 中一样。scalaz.typelevel(目前)不提供开箱即用的功能,但按照 Shapeless 作为模型,实施起来应该不会太难。

于 2012-11-13T11:51:16.060 回答
1

你可以为它定义一个幺半群。

implicit val fooMonoid = new Monoid[Foo] {
  def zero = Foo(mzero[Int], mzero[String])
  def append(f1: Foo, f2: => Foo) = Foo(Monoid[Int].append(f1.x,f2.x), Monoid[String].append(f1.y,f2.y))
}

可能有更好的方法来编写 impl,但这就是基本思想。

我猜我们可以用宏来定义一般的案例类。

于 2012-11-13T05:34:38.597 回答