当我在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,但是任何发生。
这是一个缺陷还是设计的一部分?
非常感谢提前
答案 0 :(得分:3)
3.right[String]
的类型为\/-[String, Int]
即你右边有Int
,左边有String
。但是,您还提供了String
作为右侧的后备值。
然后编译器会查找String
和Int
的最低常见超类型,它恰好是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
的超级类型。在您的示例中,B
为Int
,"123"
为String
。正如@Gabriele Petronella所指出的,BB
被推断为最常见的超常类型#34; Int
和String
,恰好是Any
。
如果签名是以下内容,那么您的示例将无法编译。
sealed abstract class \/[+A, +B] {
...
def getOrElse[B](x: => B): B = ...
def |[B](x: => B): B = ...
...
}
鉴于上述定义,x: B
,在您的示例中为Int
。 " 123"不是Int
。