2014-06-30 7 views
3

Pourquoi chaque None (de différents types Option) est-il vrai?Comparer les types différents

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

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

Les deux x et y sont Option 's de types distincts, mais leurs None' s égale les uns des autres.

scala> x == y 
res0: Boolean = true 

Pourquoi?

Répondre

8

Par conséquent, il y a exactement unNone dans votre mémoire. Donc les deux sont la même chose. Et l'identité implique évidemment l'égalité.

Quant à la question, pourquoi vous pouvez réellement comparer les deux: Cela est dû au sous-typage de Scala: Chaque Object a une méthode equals, et cette méthode est ce que vous utilisez avec l'opérateur ==.

edit: J'ai trouvé l'implémentation On github vous pouvez voir, que None est en effet un objet case. Il n'y a pas non plus de méthode equals(), donc vous utilisez celle qui est générée automatiquement pour les classes de cas. D'où le commentaire ci-dessous sur l'effacement de type s'applique également à votre cas Some().

+0

J'imagine que cela a aussi à voir avec l'effacement de type. Au moment de l'exécution, la JVM ne connaît rien au générique (sauf si vous faites des choses avec 'ClassTag' et ses semblables.) –

3

et 1 == "string" renvoie false. vérification de l'égalité standard Scala est de type pas sûr, i.e.:

final def ==(arg0: Any): Boolean 

Si vous voulez utiliser === avec Sûreté du typage Equal de scalaz classe de types. Sans regarder la mise en œuvre réelle, je suppose que None est en fait un objet de cas.

+0

Ne voudriez-vous pas compiler '1 == 1.0'? –

+0

@ Jasper-M Rien ne vous empêche de comparer ints avec doubles, si vous pouvez montrer une preuve de l'égalité des types, mais cela résoudrait des problèmes comme dans la question – 4lex1v

+0

@ Jasper-M généralement pas. Avec une valeur flottante: HELL NO. Chaque fois que vous essayez de vérifier l'égalité impliquant des nombres à virgule flottante, vous risquez de faire des erreurs. – stew

3

Il y a vraiment deux questions ici:

  1. Pourquoi x == y typecheck dans votre REPL?
  2. Pourquoi sont-ils égaux?

x == y parce == compile à Scala est de type pas en sécurité:

scala> "x" == 1 
res4: Boolean = false 

Alors pourquoi ils ne correspondraient l'autre? Un Option Scala est conceptuellement similaire à un type de données dans Haskell Algébrique:

data Maybe a = Nothing | Just a 

Mais si vous regardez le Option.scala source, vous verrez qu'un Option est défini (un peu, simplifie) comme:

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] 

Du côté Some, vous pouvez voir une classe de cas avec le type paramétré +A - de sorte qu'un Option[Int] devient Some[Int].

Cependant, du côté None, vous voyez un objet Option[Nothing], donc un noneish Option[Int] et un noneish Option[String] deux deviennent un objet Option[Nothing], et par conséquent égale les uns des autres.

Comme @TravisBrown souligne, Scalaz attrape ce beaucoup plus tôt, au moment de la compilation:

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

' Nothing' dans Haskell a le type 'Maybe a' (en l'absence d'autre contexte).' (Nothing :: Maybe Int) == (Nothing :: Maybe String) 'ne compile pas (et ne devrait pas), et le code équivalent dans Scalaz ne le sera pas non plus –

+0

Bon point @TravisBrown, j'ai mis à jour ma réponse avec Scalaz ref, merci –

2

Option est (grosso modo) mis en œuvre comme ceci:

trait Option[+A] 
case class Some[A](value: A) extends Option[A] 
case object None extends Option[Nothing] 

Parce que None est un objet, (un singleton en termes java), il y en a une seule instance, et parce que Nothing est tout en bas de la hiérarchie de type, ce qui signifie qu'il s'agit d'un sous-type de tout type en Scala (même null), les deux None s sont effectivel y le même type

Questions connexes