2012-11-13 32 views
2

随着Scalaz 7的目的的产品,我们可以为类群的产品获得零:治疗的情况下,类为的mzero

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

是否有更简单的方式来获得零的情况下类,其字段是monoids?理想情况下,不需要重复字段类型àla:

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

回答

6

即使在无形你需要一些样板,像这样:

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同构,就像在无形中。 scalaz.typelevel不(目前)提供这种开箱,但它不应该太难实现,下面无形的一种模式。

1

您可以为它定义一个monoid。

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,但那就是基本的想法。

我用宏想我们可以把它定义在一般情况下类。

+0

是啊,我定居明确定义它们现在;它只是觉得应该有更好的方法。如果没有更好的事情出现,我会接受。 – Hugh

+0

Aparently类型的东西可以在scalaz中做到。我无法正常工作。 –

+1

不成形也做了 - https://github.com/milessabin/shapeless/blob/master/examples/src/main/scala/shapeless/examples/monoids.scala –