为什么每个None
(不同的Option
类型)评估为true?
scala> val x: Option[String] = None
x: Option[String] = None
scala> val y: Option[Int] = None
y: Option[Int] = None
x
和y
都是Option
个不同的类型,但他们的None
彼此相等。
scala> x == y
res0: Boolean = true
为什么?
答案 0 :(得分:8)
不看实际的实现,我会假设None
实际上是一个案例对象。因此,你的记忆中只有一个 None
。所以两者都是一回事。身份显然意味着平等。
关于这个问题,为什么你可以实际比较两者:这是由于Scala的子类型:每个Object
都有一个equals
方法,这个方法就是你正在使用的方法使用==
运算符。
编辑:我发现你可以看到的实现On github,None确实是一个案例对象。也没有equals()方法,因此您使用的是为case类自动生成的方法。因此,下面关于类型擦除的评论也适用于您的Some()
案例。
答案 1 :(得分:3)
1 == "string"
返回false
。 Scala中的标准等式检查不是类型安全的,即:
final def ==(arg0: Any): Boolean
如果你想要类型安全,请使用===
来自scalaz的Equal
类型类。
答案 2 :(得分:3)
这里确实有两个问题:
x == y
类型检查? x == y
编译,因为Scala中的==
不是类型安全的:
scala> "x" == 1
res4: Boolean = false
那为什么他们彼此相等? Scala中的Option
在概念上类似于Haskell中的代数数据类型:
data Maybe a = Nothing | Just a
但是如果你看一下Option.scala source,你会看到Option
被定义(在某种程度上简化):
sealed abstract class Option[+A] extends Product with Serializable
final case class Some[+A](x: A) extends Option[A]
case object None extends Option[Nothing]
在Some
方面,您可以看到参数化类型为+A
的案例类 - 因此,某个Option[Int]
变为Some[Int]
。
但是,在None
方面,您会看到一个Option[Nothing]
对象,因此非Option[Int]
和非Option[String]
两者都会成为Option[Nothing]
个对象,因此彼此相等。
正如@TravisBrown指出的那样,Scalaz在编译时更早地捕获了这个:
scala> import scalaz._
scala> import Scalaz._
scala> val x: Option[String] = None
scala> val y: Option[Int] = None
scala> x === y
<console>:16: error: could not find implicit value for parameter F0: scalaz.Equal[Object]
x === y
scala> val z: Option[String] = None
scala> x === z
res3: Boolean = true
答案 3 :(得分:2)
Option
(粗略地说)实现如下:
trait Option[+A]
case class Some[A](value: A) extends Option[A]
case object None extends Option[Nothing]
因为None
是一个对象(java术语中的单例),它只有一个实例,并且因为Nothing
位于类型层次结构的最底层,意思是它是Scala中每种类型的子类型(即使为null),两个None
实际上是同一类型