scala - create Scalaz equal instance on class with subtypes -
i have following simple adt, how implement instance of equality typeclass without resorting explicitly pattern matching possible combinations?
import scalaz._ import scalaz._ sealed trait billinginfo case class creditcard(number: int, holder: string, address: string) extends billinginfo case object cod extends billinginfo case class invoice(cid: string) extends billinginfo object billinginfo{ implicit val billingequal = equal.equal[billinginfo]{(b1,b2) => (b1,b2) match { case (invoice(c1), invoice(c2)) => c1 === c2 case (creditcard(a,b,c), creditcard(d,e,f)) => === d && b === e && c === f //writing exhaustive match tedious } }
you've got (at least) 2 options. 1 use "natural" equality. if don't have custom types case class members should work fine:
implicit val billingequal: equal[billinginfo] = equal.equala[billinginfo]
or use shapeless's type class instance derivation:
import shapeless._ import scalaz.{ coproduct => _, :+: => _, _ }, scalaz._ object equalderivedorphans extends typeclasscompanion[equal] { object typeclass extends typeclass[equal] { def product[h, t <: hlist](eh: equal[h], et: equal[t]): equal[h :: t] = tuple2equal(eh, et).contramap { case h :: t => (h, t) } def project[a, b](b: => equal[b], ab: => b, ba: b => a): equal[a] = b.contramap(ab) def coproduct[l, r <: coproduct]( el: => equal[l], er: => equal[r] ): equal[l :+: r] = eitherequal(el, er).contramap { case inl(l) => left(l) case inr(r) => right(r) } val emptyproduct: equal[hnil] = equal.equal((_, _) => true) val emptycoproduct: equal[cnil] = equal.equal((_, _) => true) } } import equalderivedorphans._
this derive equal
instances case classes have equal
instances members.
or of course enumerate cases, isn't terrible:
implicit val billingequal = equal.equal[billinginfo] { case (invoice(c1), invoice(c2)) => c1 === c2 case (creditcard(a, b, c), creditcard(d, e, f)) => === d && b === e && c === f case (cod, cod) => true case _ => false }
note don't need level of matching on tuple.
Comments
Post a Comment