为了mzero的目的,将案例类作为产品处理

时间:2012-11-13 04:28:18

标签: scala scalaz

使用Scalaz 7,我们可以获得monoids产品的零:

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

对于字段为幺半群的案例类,是否有更简单的方法来获得零?理想情况下,不需要重复字段类型

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

2 个答案:

答案 0 :(得分: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 - 元组同构,它允许我们只写一个简单的Foo - HList同构,就像在Shapeless中一样。 scalaz.typelevel没有(当前)提供开箱即用的功能,但在Shapeless作为模型之后实现起来应该不会太难。

答案 1 :(得分: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,但这是基本的想法。

我想我们可以使用宏来为案例类定义它。