Разрыв с экзистенциальным типом и функцией высшего порядка

Используя некоторую структуру:

object Foo {
  trait Bar[B]
}
trait Foo[A, B, F <: Foo[A, B, F]] {
  def baz(fun: A => Foo.Bar[B] => Unit): Unit
}

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

def test[A, F <: Foo[A, _, F]](foo: F) =
  foo.baz { a => b => println(b) } 

Возникает следующая ошибка:

<console>:38: error: type mismatch;
 found   : A => Foo.Bar[(some other)_$1(in type F)] => Unit
   forSome { type (some other)_$1(in type F) }
 required: A => (Foo.Bar[_$1(in type F)] => Unit)
         foo.baz { a => b => println(b) } 
                     ^

Пока компилируется следующее:

def test[A, JamesClapperSociopath, F <: Foo[A, JamesClapperSociopath, F]](foo: F) =
  foo.baz { a => b => println(b) } 

person 0__    schedule 31.10.2013    source источник


Ответы (1)


Это должно иметь какое-то отношение к эквивалентности экзистенциальных типов. Компилятор, вероятно, выводит b: F#_$1, а затем не может понять, что две проекции равны.

К счастью, функции контравариантны по типу параметра, так что вы можете просто написать:

def test[A, F <: Foo[A, _, F]](foo: F) =
  foo.baz { a => (b: Any) => println(b) } 
person Tobias Brandt    schedule 31.10.2013
comment
В этот момент вы могли бы также использовать a => (b: Foo.Bar[_]) => println(b), который также компилируется. - person Travis Brown; 31.10.2013
comment
@TravisBrown Конечно, в данном случае это не имеет значения. - person Tobias Brandt; 31.10.2013
comment
К сожалению, println — это просто заполнитель. Конечно, мне нужно сохранить тип Foo.Bar[B]. Меня больше интересовало, почему это происходит. Между тем, моя рефакторинговая вещь — это trait Foo[A, F <: Foo[A, F]] { type B }, которая производит меньше PITA. Тогда аргумент baz имеет тип A => Foo.Bar[F#B] => Unit. - person 0__; 31.10.2013