gpt4 book ai didi

scalaz.Equal 用于路径依赖类型

转载 作者:行者123 更新时间:2023-12-04 19:58:55 24 4
gpt4 key购买 nike

我正在尝试依赖路径的类型,但在尝试编写 scalaz.Equal 时遇到了问题。例如。我有以下结构:

class A {
class B
}

val a1 = new A
val b1 = new a1.B // type a1.B

val a2 = new A
val b2 = new a2.B //type a2.B

我首先想做 b1 “无与伦比”(这是一个词吗?)到 b2在编译时,我通过以下方式实现了:
import scalaz._
import Scalaz._

implicit def BEqual[X <: A#B]: scalaz.Equal[X] = Equal.equalA

b1 === b1 //true
b1 === b2 // doesn't compile, good
b2 === b1 // doesn't compile, good

我的第二个实验是尝试减少对等式的限制,允许 A#B 的实例。相互比较,但不与其他类型进行比较,具有:
 implicit val  BEqual: scalaz.Equal[A#B] = Equal.equalA

但它没有按预期工作:
b1 === b2 //doesnt' compile, === is not a member of a1.B 

然而,这有效:
BEqual.equal(b1,b2)  //compiles
BEqual.equal(b1,"string") //doesnt' compile, good

所以,我想知道为什么 ===不起作用,如果我可以编写 Equal 的实例这将适用于所有 A#B ?

我尝试了一个带有隐式转换的自制解决方案,它奏效了。
implicit class abEqual(ab: A#B) {
def eqab(ab2: A#B) = ab == ab2
}

b1.eqab(b2) //ok
b2.eqab(b1) //ok
b1.eqab("String") //doesn't compile, good

那么为什么这不适用于 scalaz.Equal ?

最佳答案

在您的第一个 BEqual你是说对于 A#B 的任何子类型您想提供一个 Equal该子类型的实例。当编译器看到 b1 ===因此,它找到了 Equal[a.B]例如,由于 b1 的静态类型是 a.B .这使事情如您所愿。

在您的第二个 BEqual ,您正在定义一个 Equal实例仅适用于 A#B .这意味着即使 b1 === b1不会编译,因为 b1 的静态类型比 A#B 更具体, 和 Equal它的类型参数是不变的。如果您向上转换您的值,该实例将正常工作:

scala> val ab1: A#B = b1
ab1: A#B = A$B@464ef4fa

scala> val ab2: A#B = b2
ab2: A#B = A$B@2d3b749e

scala> ab1 === ab2
res1: Boolean = false

在你调用的版本 BEqual.equal直接,你基本上完成了同样的事情——方法参数总是协变的,所以当你传递静态类型为 a.B 的东西时作为 A#B争论,一切都会好起来的。在你手动滚动的隐式类中,你同样只是说你想使用任何旧的 A#B .

Some(1) === Some(1)也能看到类似的东西对比 Option(1) === Option(1) (或 some(1) === some(1))。 Scalaz 提供了一个 EqualOption[A: Equal] ,但不适用于 Some[A: Equal] ,并且当第一个参数具有更具体的静态类型时, Option找不到实例。

这不是您想要解决的问题,因为 Scalaz 的不变性 Equal是故意的。如果您想与 A#B 合作值为 A#B在这种情况下,您需要明确地向上转换它们。

关于scalaz.Equal 用于路径依赖类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30349256/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com