使用scalaz.NonEmptyList [A]作为成员的case类和===,equals,==

时间:2012-11-18 13:00:29

标签: scala equals scalaz

我想将案例类与scalaz NonEmptyList字段进行比较。 ==euqls不起作用,我知道这是因为NonEmptyList.equals方法检查比较对象是否与调用者相同。另一方面,scalaz ===函数适用于NonEmptyList,前提是范围内必须有隐式Equals

问题在于我想让我的案例类具有通用性,并且希望这个实例能够轻松比较。

怎么做?

如果唯一的解决方案是提供自定义def equals(obj: Any): Boolean方法,请在下面发布。

我的代码:

object Problem {

  case class CC[M, N](s: M, nel: NonEmptyList[N])

  CC(1, 2.wrapNel) == CC(1, 2.wrapNel) //false

  CC(1, 2.wrapNel) equals CC(1, 2.wrapNel) //false


  implicit def cCEquals[M, N] = equalA[CC[M, N]]

  CC(1, 2.wrapNel) === CC(1, 2.wrapNel) //false

  //override def equals(obj: Any): Boolean = ???
}

1 个答案:

答案 0 :(得分:3)

我知道它可能对您没有帮助,但equals上的NonEmptyList方法在Scalaz 7中按预期工作。(编辑:实际上这也是now fixed in Scalaz 6,所以如果你愿意从源代码构建或等待6.0.5,无论如何你都会好的。)

在Scalaz 6.0.4或更早版本中使用Equal解决此问题的方法仍然很自然,但您必须确保为{{1}构建正确的Equal实例}}:

CC[M, N]

我们要求implicit def ccEqual[M: Equal, N: Equal] = Equal.equalBy[CC[M, N], (M, NonEmptyList[N])] { case CC(s, nel) => (s, nel) } M都有N个实例。然后,编译器可以为Equal构建Equal实例,然后为NonEmptyList[N]构建(M, NonEmptyList[N])实例。从CC[M, N](M, NonEmptyList[N])有明显的映射,我们可以使用Equal.equalBy将其转换为所需的实例。

如果您愿意为MN使用普遍平等,则可以这样做:

implicit def ccEqual[M, N] = new Equal[CC[M, N]] {
  def equal(a: CC[M, N], b: CC[M, N]) =
    a.s == b.s && Equal.NonEmptyListEqual(Equal.equalA[N]).equal(a.nel, b.nel)
}

甚至只是:

implicit def ccEqual[M, N] = new Equal[CC[M, N]] {
  def equal(a: CC[M, N], b: CC[M, N]) = a.s == b.s && a.nel.list == b.nel.list
}

使用一点类型魔法(例如通过Scalaz 7 typelevel或更容易使用Shapeless),您可以让编译器为Equal个实例生成Equal个实例1}}成员的实例,但自己写出来并不难。