A couple of questions arise while I'm reading 7.3.2 Capturing type constraints from Joshua's Scala in Depth. The example excerpted from the book:
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))
It seems straightforward that C
is found to be List[Int]
by the 1st parameter list. And how <:<
enforces type constraint by variance is explained in the book. But I don't quite see how that helps to find A
.
My understanding is, from 1st parameter list, scala finds out C: List[Int]
, then it looks for implicit ev: <:<[List[Int], Traversable[A]]
. At the moment A
remains unknown. It "pulls" two implicits conforms[List[Int]]
and conforms[Traversable[A]]
to match ev
. In either case to satisfy variance, List[Int] <: Traversable[A]
has to be satisfied, which leads to the finding that A
is Int
.
Does it work as what I'm describing here? Especially on how/when A
is deduced.
What Are Implicit Parameters? Implicit parameters are similar to regular method parameters, except they could be passed to a method silently without going through the regular parameters list. A method can define a list of implicit parameters, that is placed after the list of regular parameters.
The implicit parameter in Java is the object that the method belongs to. It's passed by specifying the reference or variable of the object before the name of the method. An implicit parameter is opposite to an explicit parameter, which is passed when specifying the parameter in the parenthesis of a method call.
The implicit system in Scala allows the compiler to adjust code using a well-defined lookup mechanism. A programmer in Scala can leave out information that the compiler will attempt to infer at compile time. The Scala compiler can infer one of two situations: A method call or constructor with a missing parameter.
Implicit parameters are the parameters that are passed to a function with implicit keyword in Scala, which means the values will be taken from the context in which they are called.
As pedrofurla commented, you've got it right—with one little qualification. You say that the compiler "pulls" conforms[Traversable[A]]
, but there's really no need for any such instance here. To take a simplified example where it's very clear what implicits are in scope:
trait Foo[-From, +To] implicit object intListFoo extends Foo[List[Int], List[Int]]
Now there's definitely no Foo[Traversable[Int], Traversable[Int]]
around, but we can write the following:
scala> implicitly[Foo[List[Int], Traversable[Int]]] res0: Foo[List[Int],Traversable[Int]] = intListFoo$@8e760f2
More or less exactly the same thing is happening in your example. In that case we would have an instance Traversable[Int] <:< Traversable[Int]
around if we needed it, but we don't for that specific implicit search.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With