2

我想将案例类与 scalazNonEmptyList字段进行比较。==oreuqls不起作用,我知道这是因为方法NonEmptyList.equals检查比较对象是否与调用者相同。另一方面,如果必须在范围内隐含,则 scalaz===函数可以正常工作。NonEmptyListEquals

问题是我想让我的案例类通用,并希望它的实例易于比较。

这该怎么做?

如果唯一的解决方案是提供自定义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 = ???
}
4

1 回答 1

3

我知道它可能对您没有帮助,但是该equals方法NonEmptyList在 Scalaz 7 中按预期工作。(编辑:实际上这现在在 Scalaz 6中也已修复,所以如果您愿意从源代码构建或等待 6.0. 5,你会没事的。)

不过,在 Scalaz 6.0.4 或更早版本中仍然有一种自然的方法可以解决这个问题Equal——您只需要确保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实例 forNonEmptyList[N]然后 for (M, NonEmptyList[N])CC[M, N]并且有一个从到的明显映射(M, NonEmptyList[N]),我们可以用 将其转换为所需的实例Equal.equalBy

如果您愿意对Mand使用普遍平等N,您可以这样做:

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 7typelevel或更容易使用Shapeless),您可以让编译器Equal为任何带有其成员实例的案例类生成实例Equal,但自己写出来并不难。

于 2012-11-18T14:30:59.203 回答