Подтвердить что ты не робот

Несколько ограничений нижнего уровня в Scala

Я заметил, что tuple.productIterator всегда возвращает Iterator[Any] заданное, если невозможно установить несколько нижних границ (так что это может быть Итератор самого низкого общего супер-типа).

Я попробовал и немного искал, но нашел только этот вопрос для нескольких верхних границ.

Это мой тест о том, как определить тип итератора:

def f[A,B](a:A, b:B) = List(a,b)
// return type is List[Any]

def f[A,B, T >: A "and" T >: B](a:A, b:B) = List[T](a,b)
// doesn't compile, but
//  f(1, true) should give a List[AnyVal] and
//  f("x", "y") a List[String]

Является ли это ограничением JVM?


Редактировать: Вот несколько больший пример, который, по-видимому, не может быть разрешен с использованием подхода IttayD, когда T должен быть определен в методе:
class Foo[A, B](a: A, b: B) {
  def f[T >: A] = List[T](a) // works
  def g[T >: A "and" T >: B] = List[T](a) // doesn't work
}
4b9b3361

Ответ 1

Для простого случая, когда A и B связаны компилятором в то же время, что и T, ответ IttayD отлично работает:

def f[T, A <: T,B <: T](a:A, b:B) = List[T](a,b)

Когда A и B уже связаны как в вашем примере class Foo[A, B], вам нужно ввести временные фиктивные переменные, чтобы компилятор выполнил это задание:

class Foo[A, B](a: A, b: B) {
  def g[T, A1 >: A <: T, B1 >: B <: T] = List[T](a.asInstanceOf[T], b.asInstanceOf[T])
}

(Для ясности: A1 >: A <: T означает, что тип A1 должен быть супертипом A и подтипом T, а не тем, что A является подтипом как A1, так и T.)

A1 и B1 приведены здесь с единственной целью вывести правильный тип для T. Если компилятор должен их вывести, они будут разрешены к A1 = A и B1 = B, а затем T как наиболее конкретный тип, который является суперклассом как A, так и B.

Однако одна вещь, которую компилятор не понимает, заключается в том, что по транзитивности мы имеем как T >: A, так и T >: B, которые непосредственно следуют из ограничений по A1 и B1. Поэтому мы должны явно бросить здесь. Но здесь литье всегда безопасно.

Теперь Product#productIterator не мог использовать эту технику, как она определена в месте, где мы даже не знаем A и B, или действительно, сколько параметров типа есть в конкретном подклассе.