比较不同类型的无

时间:2014-06-30 17:36:56

标签: scala

为什么每个None(不同的Option类型)评估为true?

scala> val x: Option[String] = None
x: Option[String] = None

scala> val y: Option[Int] = None
y: Option[Int] = None

xy都是Option个不同的类型,但他们的None彼此相等。

scala> x == y
res0: Boolean = true

为什么?

4 个答案:

答案 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)

这里确实有两个问题:

  1. 为什么你的REPL中有x == y类型检查?
  2. 为什么他们彼此相等?
  3. 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实际上是同一类型