2012-11-13 66 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 –