2016-06-05 3 views
0

У меня есть следующее определение функции в Скале:Почему Scala не распознает тип Null в качестве подтипа T в выводе параметра типа универсальной функции?

trait GenExtractor[+R] P 
     def orElseExtractor[R2<: Super, Super>: R](g: GenExtractor[T, R2]): GenExtractor[T, Super] = 
     new OrElse[T, Super](this, g) 
} 

, который должен объединить 2 GenExtractors:

GenExtractor[A] 
GenExtractor[B] 

в:

GenExtractor[C] 

где С является общим супертипом А и В

Однако, когда я пытаюсь вызвать эту функцию п:

val genExtractor = new GenExtractor[R](...parameters...) 
val combined = genExtractor.orElseExtractor[Null, R] { 
     _: FetchedRow => null 
    } 

Я получил следующее сообщение об ошибке:

Error:(84, 47) type arguments [Null,R] do not conform to method orElseExtractor's type parameter bounds [R2 <: Super,Super >: R] 
    def orNull: Extractor[R] = orElseExtractor[Null, R] { 
              ^

Это явно ложный сигнал тревоги, так как в этом случае:

type R2 = Null 
type Super = R 

которые удовлетворяют условию: Null <: R & R>: R

Почему компилятор scala дал мне эту ошибку? Что мне делать, чтобы исправить это?

ответ

3

Зачем нужен Null подтип общего типа R? Это не компилятор, находящийся вне знака, это основное предположение, что Null <: R всегда верно. Вот несколько интересных примеров, и они связаны с примитивами.

Some(5).orNull даст error: Cannot prove that Null <:< Int

Вот ваш разрыв, вы можете попробовать его в РЕПЛ:

implicitly[Null <:< AnyRef] // will compile 
implicitly[Null <:< AnyVal] // blows up, primitives are not included. 

В системе типа, надтипа всех типов, единственное, что гарантированно удовлетворить любые такие отношения, как вы ожидаете, это scala.Nothing, а не scala.Null.

null на JVM предназначен, главным образом, для того, чтобы справиться с отсутствием информации о типе, а не заниматься иерархией системного типа. Для этого у вас есть Nothing, AnyRef, AnyVal и все другие забавные вещи.

Смежные вопросы