Есть ли сокращение для переменной типа 'm forSome { type m[O] ‹: UpperBound[O] }` в Scala?

Проблема:

trait UpperBound[O]
trait High[F[O] <: UpperBound[O]]

def canEqual(that :Any) = that.isInstanceOf[High[_]]

def high(h :High[_]) = ???

Не компилируется, потому что scalac видит тип _ вместо ожидаемого конструктора типа. Как это исправить, в идеале без написания романа?

Исходный вопрос (до редактирования в ответ на ответ Дмитрия) имел:

def canEqual(that :Any) = that.isInstanceOf[High[m forSome { type m[O] <: UpperBound[O] }]]

def high(h :High[m forSome { type m[O] <: UpperBound[O] }] = ???

Есть ли более короткий способ написать два вышеуказанных метода, используя какое-то выражение с подстановочными знаками? Простое использование _ в позиции параметра типа High не работает, поскольку тип не совпадает, а _[_] даже не является допустимым выражением типа.


person Turin    schedule 05.04.2020    source источник
comment
Что касается вашего обновленного вопроса, вы имеете в виду только def high(h: High[F] forSome {type F[O] <: UpperBound[O] }) = ????   -  person Dmytro Mitin    schedule 05.04.2020
comment
Интересно. Я никогда не знал, что есть разница между тем, что я написал в исходном вопросе, и вашим фрагментом здесь. Мне нужно перечитать SLS внимательнее, потому что я вообще не вижу, откуда он берется.   -  person Turin    schedule 06.04.2020
comment
Ну, думаю, понятно, что List[X[A]] forSome { type A } и List[X[A] forSome { type A }] разные. Первый состоит из элементов, имеющих типы X[A], где A произвольный, но одинаковый для всех элементов. Последний состоит из элементов, имеющих типы X[A], где A произволен и может быть разным для разных элементов.   -  person Dmytro Mitin    schedule 06.04.2020
comment
Да, теперь, когда вы упомянули об этом, это вроде как очевидно. В свою защиту я использовал его в контексте одного значения, поэтому семантика естественного языка была такой же.   -  person Turin    schedule 07.04.2020


Ответы (1)


  • Если вы делаете экзистенциальное квантование за пределами High, то это просто

    type T = High[F] forSome { type F[O] <: UpperBound[O] }
    
    def canEqual(that: Any) = that.isInstanceOf[T]
    
    def high(h: T) = ???
    
  • #P2#
    implicitly[(n forSome { type n <: Upper}) =:= Upper]
    implicitly[(m[O1] forSome { type m[O] <: UpperBound[O]}) =:= UpperBound[O1]]
    
    #P3#
    implicitly[High[m forSome { type m[O] <: UpperBound[O] }] =:= High[UpperBound]]
    
    def canEqual(that: Any) = that.isInstanceOf[High[UpperBound]]
    
    def high(h: High[UpperBound]) = ???
    
    <цитата> #P4# #P5#
person Dmytro Mitin    schedule 05.04.2020
comment
High в примере является инвариантным относительно своего параметра типа, поэтому замена не применяется. Учитывая LowerBound[O] extends UpperBound[O], High[LowerBound] не является подтипом High[UpperBound]. - person Turin; 05.04.2020
comment
Хорошо, видимо то, что я написал, не то, что я имел в виду, извините! Меня интересовала «стертая» форма High[_], которая не вызывала бы предупреждений при использовании в isInstanceOf/сопоставлении с образцом и и была бы супертипом любого экземпляра High. Не знаю, как это перефразировать, но попробую. - person Turin; 05.04.2020
comment
@Turin Да, что касается вашего первого комментария, дисперсия High не имеет значения, важно то, что появление m в m[O1] является ковариантным, поэтому (m[O1] forSome { type m[O] <: UpperBound[O]}) =:= UpperBound[O1] для всех O1. - person Dmytro Mitin; 05.04.2020
comment
Тем не менее, с trait Lower[O] exteds UpperBound[O] код high(new High[Lower]) не компилируется, и это меня немного удивляет. Иду в SLS, чтобы снова прочитать этот раздел, но я чувствую, что упускаю что-то очевидное... - person Turin; 06.04.2020
comment
@Turin Похоже, какая-то проблема с выводом типа. Для type T = High[F] forSome {type F[O] <: UpperBound[O] } def high(h: T) = ???: implicitly[High[Lower] <:< T] компилируется, new High[Lower] {} : High[Lower] компилируется, new High[Lower] {} : T не компилируется, high(new High[Lower] {}) не компилируется, high(new High[Lower] {} : High[Lower]) компилируется, high(new High[Lower] {} : T) не компилируется, high((new High[Lower] {} : High[Lower]) : T) компилируется. Скала 2.13.1. - person Dmytro Mitin; 06.04.2020