Scala: параметр типа коллекции выдерживает "сбор", когда параметр типа является типом элемента

Обычно при сборе всех элементов последовательности, которые соответствуют определенному типу, результирующая коллекция имеет как тип исходной коллекции, так и тип, выбранный для:

trait Foo
trait Bar

trait Baz {
  // Works
  def def1(foo: Seq[Foo]): Seq[Foo with Bar] = 
    foo collect {case foobar: Bar => foobar}
}

Это даже работает, когда входной тип параметризован ограниченным типом члена, и все, что я хочу вернуть, - это последовательность, параметризованная связанным типом (не типом члена):

trait Baz {
  type memberType <: Foo

  // Works
  def2(foo: Seq[memberType]): Seq[Foo with Bar] =
    foo collect {case foobar: Bar => foobar}
}

Однако, это терпит неудачу, когда я действительно хочу вернуть последовательность, параметризованную типом члена:

trait Baz {
  type memberType <: Foo

  // Fails
  def def3(foo: Seq[memberType]): Seq[memberType with Bar] =
    foo collect {case foobar: Bar => foobar}
}

Сообщение об ошибке:

error: type mismatch;
 found   : Seq[this.Foo with this.Bar]
 required: Seq[Baz.this.memberType with this.Bar]
    foo collect {case foobar: Bar => foobar}

Чтобы восстановить функциональность, я могу включить тип члена в collect вызов, но это кажется избыточным, учитывая, что каждый элемент должен соответствовать этому типу из-за подписи:

trait Baz {
  type memberType <: Foo

  // Works
  def def4(foo: Seq[memberType]): Seq[memberType with Bar] =
    foo collect {case foobar: memberType with Bar => foobar}
}

Есть ли способ определить последовательность типов элементов, чтобы они помнили свои типы элементов, когда collectред?

1 ответ

Это не ответ, а просто наблюдение. Это работает:

trait Baz[A <: Foo] {
  def def3(foo: Seq[A]): Seq[A] =
    foo collect {case foobar => foobar}
}

но это не

trait Baz[A <: Foo] {
  def def3(foo: Seq[A]): Seq[A] =
    foo collect {case foobar: Bar => foobar}
}

также это не:

trait Baz[A] {
  def def3(foo: Seq[A]): Seq[A] =
    foo collect {case foobar: Bar => foobar}
}

так что это похоже на эффект сопоставления с образцом; Я не думаю, что это имеет какое-либо отношение к collect особенно. Каким-то образом он теряет информацию, как только вы добавляете тип в регистр соответствия:-/

Но, как и Кайто, я тоже был удивлен, что ваши первые два дела сработали. Должно быть (и это кажется разумным), чтобы алгоритм вывода типа отличал известный стабильный тип (Foo) и параметр типа или член типа. Возможно, вам придется спросить в списке рассылки scala language, чтобы некоторые гуру компиляторов ответили на вопрос...

Другие вопросы по тегам