使用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,)
答案 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,但这是基本的想法。
我想我们可以使用宏来为案例类定义它。