2

当我在 Scalaz 中使用 Either 类型时,这是一个非常好的设计,但方法 getOrElse 会丢失类型推断。

val either = ~3.right[String] | "123" // either: String

val either = 3.right[String] | "123" // either: Any

为什么 val 要么 = 3.right[String] | “123”不是指 Int,而是 Any 发生。

这是一个缺陷还是设计的一部分?

提前谢谢了

4

2 回答 2

3

3.right[String]是类型,\/-[String, Int] 即您Int在右侧有一个String,在左侧有一个。但是,您还为String右侧提供了一个备用值。

然后编译器查找 and 的最低公共超类型StringInt恰好是Any

请记住,类型参数将提供有关“缺失”方面的信息:如果您有 a right,它将标记 的类型,left反之亦然。

在第一种情况下,您说:我有一个 left Int,我的 right 将是 a String(这与作为右后备值传递的 "123" 一致)

在后者中,您是说:我有一个 right Int,我的 left 将是 a String,但是您随后提供了 aString作为权利。

于 2014-10-10T09:24:43.683 回答
0

发生这种情况的原因是 and 的定义中的类型BB >: B约束。见https://github.com/scalaz/scalaz/blob/series/7.2.x/core/src/main/scala/scalaz/Either.scala#L202-L210|\/

sealed abstract class \/[+A, +B] {
...
  def getOrElse[BB >: B](x: => BB): BB = ...

  def |[BB >: B](x: => BB): BB = ...
...
}

BB >: B意味着BB必须是 的超类型B。在您的示例中,BisInt"123"is String。正如@Gabriele Petronella 指出的那样,BB被推断为 and 的“最低常见超类型” IntString恰好是Any.

如果签名如下所示,则您的示例将无法编译。

sealed abstract class \/[+A, +B] {
...
  def getOrElse[B](x: => B): B = ...

  def |[B](x: => B): B = ...
...
}

鉴于上述定义,x: B,在您的示例中是Int。“123”不是Int

于 2014-10-10T15:02:25.233 回答