为什么getOrElse会丢失scalaz中的类型推断

时间:2014-10-10 06:17:45

标签: scala scalaz scalaz7

当我在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,但是任何发生。

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

非常感谢提前

2 个答案:

答案 0 :(得分:3)

3.right[String]的类型为\/-[String, Int] 即你右边有Int,左边有String。但是,您还提供了String作为右侧的后备值。

然后编译器会查找StringInt的最低常见超类型,它恰好是Any

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

在第一种情况下,你说:我左边是Int,我的右边是String(与右边后退值一致的“123”一致)

在后者中你说:我有一个正确的Int,我的左边是String,但你提供的是String作为权利。

答案 1 :(得分:0)

发生这种情况的原因是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的超级类型。在您的示例中,BInt"123"String。正如@Gabriele Petronella所指出的,BB被推断为最常见的超常类型#34; IntString,恰好是Any

如果签名是以下内容,那么您的示例将无法编译。

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

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

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