scalaz.Equal 用于路径依赖类型

标签 scala scalaz path-dependent-type

我正在尝试依赖路径的类型,但在尝试编写 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/

相关文章:

java - 将任意类型安全配置写入 hocon 文件的标准化方法?

scala - Spark 2.2 : Load org. apache.spark.ml.feature.LabeledPoint 来自文件

scala - scalaz中的商店是什么

scala - 是否有关于如何使用这种结构类型的综​​合教程?

scala - 为什么一旦我向类型引入参数,它就会停止工作? (斯卡拉)

scala - 合并 scalaz-stream 输入进程在 stdin 上似乎为 "wait"

scala - 避免使用类型成员和子类型进行类型转换

scala - scala中不同路径依赖类型的特点

scala - 如何在 Scala 中使用具有类型类的路径相关类型

scala - 如何转换 Spark 数据框以使我的值成为列名称?