Как неявный <: <помогает найти параметры типа
Несколько вопросов возникают, когда я читаю 7.3.2 Ограничения типа захвата
от Джошуа Scala в глубину. Пример, взятый из книги:
scala> def peek[C, A](col: C)(implicit ev: C <:< Traversable[A]) = (col.head, col)
peek: [C, A](col: C)(implicit ev: <:<[C,Traversable[A]])(A, C)
scala> peek(List(1, 2, 3))
res9: (Int, List[Int]) = (1,List(1, 2, 3))
Кажется очевидным, что C
оказывается List[Int]
по 1-му параметру
список. И как <:<
применяет ограничение типа по дисперсии, объясняется в книге.
Но я не совсем понимаю, как это помогает найти A
.
Я понимаю, что из первого списка параметров Scala обнаруживает C: List[Int]
,
то он ищет implicit ev: <:<[List[Int], Traversable[A]]
.
На данный момент A
остается неизвестным.
Он "тянет" два имплицита conforms[List[Int]]
и conforms[Traversable[A]]
в
соответствие ev
. В любом случае для удовлетворения дисперсии должно выполняться List[Int] <: Traversable[A]
, что приводит к выводу, что A
Int
.
Работает ли он так, как я описываю здесь? Особенно в том, как/когда A
выводится.
Ответы
Ответ 1
Как прокомментировал педрофурла, у вас все получилось - с небольшой квалификацией. Вы говорите, что компилятор "тянет" conforms[Traversable[A]]
, но здесь нет необходимости в каком-либо таком экземпляре. Чтобы упростить пример, где он очень четко показывает, какие импликации находятся в области видимости:
trait Foo[-From, +To]
implicit object intListFoo extends Foo[List[Int], List[Int]]
Теперь определенно нет Foo[Traversable[Int], Traversable[Int]]
, но мы можем написать следующее:
scala> implicitly[Foo[List[Int], Traversable[Int]]]
res0: Foo[List[Int],Traversable[Int]] = [email protected]
Более или менее точно то же самое происходит в вашем примере. В этом случае мы бы имели экземпляр Traversable[Int] <:< Traversable[Int]
вокруг, если бы нам это было нужно, но мы не для этого конкретного неявного поиска.