2014-12-24 2 views
0

Этот код компилируется так же, как хорошо:Тип псевдонима A не эквивалентен A?

type Named[A] = (String, A) 

def foo[A](a: A) = {} 

trait Elem[A] 

val m = Map[String, Elem[_]]() 

m.foreach(e => foo[Named[Elem[_]]](e)) 

Однако это один не делает:

type NamedElem[A] = Named[Elem[A]] 

m.foreach(e => foo[NamedElem[_]](e)) 

Сообщение об ошибке не объясняет, почему:

type mismatch; 
found : (String, Elem[_]) 
required: NamedElem[_] 
    (which expands to) (String, Elem[_$2]) forSome { type _$2 } 
       Map[String, Elem[_]]().foreach(e => foo[NamedElem[_]](e)) 
                    ^

Таким образом, очевидно NamedElem[A] не Named[Elem[A]]. Это предполагаемое поведение? Или я чего-то не хватает?

Спасибо!

ответ

2

Это связано только с экзистенциальными типами. Это компилируется нормально:

type Named[A] = (String, A) 

def foo[A](a: A) = {} 

trait Elem[A] 

val m = Map[String, Elem[Int]]() 

m.foreach(e => foo[Named[Elem[Int]]](e)) 

type NamedElem[A] = Named[Elem[A]] 

m.foreach(e => foo[NamedElem[Int]](e)) 

_ просто синтаксис для forSome. В вашем случае:

NamedElem[_] расширяется до (String, Elem[T]) forSome { type T }, в то время как Named[Elem[_]] расширяется до (String, Elem[T] forSome { type T })

Так что да, NamedElem[_] и Named[Elem[_]] различные типы.

Вы можете найти более подробную информацию в моем старом вопросе: Existensial types in Scala

+0

Спасибо @ dk14, поэтому 'Названа [Эль [A]]' не 'NamedElem [A]' 'когда A' экзистенциальный тип , Как вы думаете, мы можем предотвратить эту разницу? Я имею в виду, есть ли способ объявить 'тип NamedElem [A]', который полностью эквивалентен 'Named [Elem [A]]'? –

+0

@ RyoichiroOka Это _is_ эквивалентно для каждого типа 'A'. Проблема в том, что '_' не является типом. –

+1

Существует только способ объявления соответствующих экзистенциальных (если они вам действительно нужны) - 'type NamedElem_ = Named [Elem [T] forSome {type T}]'. Как сказал Алексей Романов, это уже эквивалентно для непиковых дженериков. Попытка унифицировать его не имеет смысла ... просто посмотрите на desugaring - '_' - это всего лишь синтаксис сахара на' forSome', а не тип сам. Определение экзистенциального типа здесь '{type T}' inside 'forSome', даже' T' внутри 'Elem [T]' (это просто ref) – dk14

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