Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在具有子类型的类上创建Scalaz equal实例_Scala_Scalaz - Fatal编程技术网

在具有子类型的类上创建Scalaz equal实例

在具有子类型的类上创建Scalaz equal实例,scala,scalaz,Scala,Scalaz,我有以下简单的ADT,如何实现equality typeclass的实例而不诉诸于显式模式匹配所有可能的组合 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 In

我有以下简单的ADT,如何实现equality typeclass的实例而不诉诸于显式模式匹配所有可能的组合

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)) =>
        a === d &&
        b === e &&
        c === f //writing exhaustive match would be tedious
    }
  }
你(至少)有两个选择。一是使用“自然”平等。如果您没有案例类成员的任何自定义类型,这应该可以正常工作:

implicit val BillingEqual: Equal[Billinginfo] = Equal.equalA[Billinginfo]
或者可以使用Shapess的类型类实例派生:

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: A => 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._

请注意,您不需要在元组上进行额外级别的匹配。

应该向Billinginfo伴随对象添加“自然”相等(隐式val BillingEqual:Equal[Billinginfo]=Equal.equalA[Billinginfo])以启用Invoice(1)==Invoice(1)?@user2726995是的
=
语法将起作用,但是我们只能在幕后使用
=
。啊,必须显式地键入发票(“a”)作为Billinginfo才能获得它。谢谢
implicit val BillingEqual = Equal.equal[Billinginfo] {
  case (Invoice(c1), Invoice(c2)) => c1 === c2
  case (CreditCard(a, b, c), CreditCard(d, e, f)) =>
    a === d && b === e && c === f
  case (COD, COD) => true
  case _ => false
}