Scala asInstanceOf with parameterized types - scala

I would like to write a function that casts to type A, where A can be e.g. List[Int], or a more complicated parameterized type like Map[Int, List[Int]].
def castToType[A](x: Any): A = {
// throws if A is not the right type
x.asInstanceOf[A]
}
Right now, due to type erasure (I believe), the code merrily works even when the type is not correct. The error only manifests on access, witha ClassCastException.
val x = List(1, 2, 3)
val y = castToType[List[String]](x)
y(0) --> throws java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
Is there a way I can use manifests to make this work properly? Thanks!

Unfortunately, this in an inherent limitation of asInstanceOf. I'm actually surprised to see the scaladoc mention it in details:
Note that the success of a cast at runtime is modulo Scala's erasure semantics. Therefore the expression 1.asInstanceOf[String] will throw a ClassCastException at runtime, while the expression List(1).asInstanceOf[List[String]] will not. In the latter example, because the type argument is erased as part of compilation it is not possible to check whether the contents of the list are of the requested type.
If you're mainly concerned about failing fast on wrong cast for traversable which would likely be the main issue when getting stuff back from your DB/memcached interface, I was playing around forcing a cast of the head for traversable objects:
def failFastCast[A: Manifest, T[A] <: Traversable[A]](as: T[A], any: Any) = {
val res = any.asInstanceOf[T[A]]
if (res.isEmpty) res
else {
manifest[A].newArray(1).update(0, res.head) // force exception on wrong type
res
}
}
On a simple example it works:
scala> val x = List(1, 2, 3): Any
x: Any = List(1, 2, 3)
scala> failFastCast(List[String](), x)
java.lang.ArrayStoreException: java.lang.Integer
[...]
scala> failFastCast(List[Int](), x)
res22: List[Int] = List(1, 2, 3)
But not on a more complex one:
val x = Map(1 -> ("s" -> 1L)): Any
failFastCast(Map[Int, (String, String)](), x) // no throw
I wonder if there is a way to recursively drill down into A to keep casting until there is no more type parameters...

You are indeed correct - type erasure means that you cannot "cast" in such a way as to distinguish between List[Int] and List[String], for example. However, you can improve on the cast which you are performing, whereby A is erased in such a way as to mean that you cannot distinguish between an Int and a String:
def cast[A](a : Any) = a.asInstanceOf[A]
//... is erased to
def erasedCast(a : Any) = a.asInstanceOf[Any]
What you need are reified generics, using manifests
def cast[A <: AnyRef : Manifest](a : Any) : A
= manifest[A].erasure.cast(a).asInstanceOf[A]
Whilst the final cast is erased to AnyRef, at least you should have the correct Class[_] instance (manifest.erasure) to get the top level type correct. In action:
scala> cast[String]("Hey")
res0: String = Hey
scala> cast[java.lang.Integer]("Hey")
java.lang.ClassCastException
at java.lang.Class.cast(Class.java:2990)
at .cast(<console>:7)
at .<init>(<console>:9)
scala> cast[List[String]](List("Hey"))
res2: List[String] = List(Hey)
scala> cast[List[Int]](List("Hey"))
res3: List[Int] = List(Hey)
My advice is not to use nested reflection to decide whether the target was really a List[Int]: this is not generally feasible. For what should the following return?
cast[List[Int]](List[AnyVal](1, 2))

You could use shapeless's Typeable from Miles Sabin:
Type casting using type parameter
It handles erasure in many cases, though only specific ones:
scala> import shapeless._; import syntax.typeable._
import shapeless._
import syntax.typeable._
scala> val x = List(1, 2, 3)
x: List[Int] = List(1, 2, 3)
scala> val y = x.cast[List[String]]
y: Option[List[String]] = None
To see the set of cases that it handles you can refer to its source:
https://github.com/milessabin/shapeless/blob/master/core/src/main/scala/shapeless/typeable.scala

Yes, the problem occurs due to type erasure. If you try
val x = List(1,2,3)
val y = castToType[Int](x)
The exception is thrown right away, as expected. The same occurs when trying to cast to Array[String] or even Array[Int].
I don't think you can create a generic type converter that works will types inside collections and other objects. You will need to create a converter for each object type. For example:
def castToType[A](x: List[A]) = x.map(i => i.asInstanceOf[A])

Consider this solution:
trait -->[A, B] {
def ->(a: A): B
}
implicit val StringToInt = new -->[String, Int] {
def ->(a: String): Int = a.toInt
}
implicit val DateToLong = new -->[java.util.Date, Long] {
def ->(a: java.util.Date): Long = a.getTime
}
def cast[A,B](t:A)(implicit ev: A --> B):B= ev.->(t)
The advantage is that:
It is type safe - the compiler will tell you if the type cannot be casted
You can define casting rules by providing proper implicits
Now you can use it so:
scala> cast(new java.util.Date())
res9: Long = 1361195427192
scala> cast("123")
res10: Int = 123
EDIT
I've spent some time and wrote this advanced code. First let me show how to use it:
scala> "2012-01-24".as[java.util.Date]
res8: java.util.Date = Tue Jan 24 00:00:00 CET 2012
scala> "2012".as[Int]
res9: Int = 2012
scala> "2012.123".as[Double]
res12: Double = 2012.123
scala> "2012".as[Object] // this is not working, becouse I did not provide caster to Object
<console>:17: error: could not find implicit value for parameter $greater: -->[String,Object]
"2012".as[Object]
^
Pretty nice? See the scala magic:
trait -->[A, B] {
def ->(a: A): B
}
implicit val StringToInt = new -->[String, Int] {
def ->(a: String): Int = a.toInt
}
implicit val StringToDate = new -->[String, java.util.Date] {
def ->(a: String): java.util.Date = (new java.text.SimpleDateFormat("yyyy-MM-dd")).parse(a)
}
implicit val StringToDouble = new -->[String, Double] {
def ->(a: String): Double = a.toDouble
}
trait AsOps[A] {
def as[B](implicit > : A --> B): B
}
implicit def asOps[A](a: A) = new AsOps[A] {
def as[B](implicit > : A --> B) = > ->(a)
}

Related

Collect instances via LiftAll

I'm trying to describe the types which a case class contains.
import shapeless._
import shapeless.ops.hlist.LiftAll
trait Desc[T] {
def description: String
}
case class Foo(f: Int)
object Foo {
implicit val description: Desc[Foo] = new Desc[Foo] { val description = "foo" }
}
case class SomeCaseClass(f: Foo)
val gen = Generic[SomeCaseClass]
val lifted = implicitly[LiftAll[Desc, gen.Repr]].instances.toList
Gives me
could not find implicit value for parameter toTraversableAux: shapeless.ops.hlist.ToTraversable.Aux[shapeless.ops.hlist.LiftAll[Playground.this.Desc,Playground.this.gen.Repr]#Out,List,Lub]
not enough arguments for method toList: (implicit toTraversableAux: shapeless.ops.hlist.ToTraversable.Aux[shapeless.ops.hlist.LiftAll[Playground.this.Desc,Playground.this.gen.Repr]#Out,List,Lub])toTraversableAux.Out.
Unspecified value parameter toTraversableAux.
Scastie here: https://scastie.scala-lang.org/bXu71pMQQzCqrrsahVBkWA
When you summon an implicit instance with implicitly[LiftAll[Desc, gen.Repr]] then the dependent type Out of LiftAll is lost, so the compiler doesn't know which type exactly instances will return.
To work around this problem most typeclasses in Shapeless define an apply method in their companion object which does retain all dependent type information. It's the reason that you can use gen.Repr in a meaningful way after calling val gen = Generic[SomeCaseClass]. For some reason however LiftAll.apply was not implemented in this way. So that leaves you the option of implementing your own implicitly, or since you're using Shapeless anyway, use its the which is supposed to be a better implicitly.
scala> def impl[T <: AnyRef](implicit ev: T): ev.type = ev
impl: [T <: AnyRef](implicit ev: T)ev.type
scala> impl[LiftAll[Desc, gen.Repr]].instances.toList
res1: List[Desc[Foo]] = List(Foo$$anon$1#40b3708a)
scala> the[LiftAll[Desc, gen.Repr]].instances.toList
res2: List[Desc[Foo]] = List(Foo$$anon$1#40b3708a)
You can see the difference here in the inferred types that the REPL displays:
scala> impl[LiftAll[Desc, gen.Repr]]
res3: LiftAll.Aux[Desc,Foo :: HNil,Desc[Foo] :: HNil] = shapeless.ops.hlist$LiftAll$$anon$206#384d060c
scala> implicitly[LiftAll[Desc, gen.Repr]]
res4: LiftAll[Desc,gen.Repr] = shapeless.ops.hlist$LiftAll$$anon$206#30787774

Cast a variable to runtime type from existential typed TypeCast in Scala

This thread addressed how to use TypeTag to get runtime type of type parameters when used with Existential type. Another thread addressed how to cast a variable to its runtime type retrieved from TypeTag.
My question builds on the aforementioned threads (kind of a combination of the two scenarios). Parts of the code is duplicated from the two threads for clarity.
scala> import scala.reflect.runtime.universe._
import scala.reflect.runtime.universe._
scala> def cast[A](a: Any, tt: TypeTag[A]): A = a.asInstanceOf[A]
cast: [A](a: Any, tt: reflect.runtime.universe.TypeTag[A])A
scala> abstract class Animal[T](implicit tt: TypeTag[T]) {
| val ttag = tt
| }
defined class Animal
scala> case object Dog extends Animal[Int]
defined object Dog
scala> case object Cat extends Animal[String]
defined object Cat
scala> val aa: List[(Animal[_], Any)] = List((Dog, 5), (Cat, "stringgg"), (Dog, 2))
aa: List[(Animal[_], Any)] = List((Dog,5), (Cat,stringgg), (Dog,2))
scala> aa(0)._1.ttag
res25: reflect.runtime.universe.TypeTag[_] = TypeTag[Int]
scala> aa(1)._1.ttag
res26: reflect.runtime.universe.TypeTag[_] = TypeTag[String]
scala> cast(aa(0)._2, aa(0)._1.ttag)
res27: Any = 5
scala> cast(aa(1)._2, aa(1)._1.ttag)
res28: Any = stringgg
In short, the last two lines: cast(value, TypeTag[_]) always return a value of type Any. But my intention is to cast these values to the correct type stored in Dog|Cat.ttag, which, unfortunately, is not TypeTag[Int] or TypeTag[String] but TypeTag[_] due to usage of existential type. Is there any solution for it?
Edit 1:
Despite the field ttag is of type TypeTag[_], ttag.tpe does have the right "type" (but as an instance of reflect.runtime.universe.Type). Is it possible to use the typetag.tpe to cast to the right type?
You could change the cast method as,
def cast[A](a: Any, tt: TypeTag[_]): A = a.asInstanceOf[A] and
val x: Int = cast(aa(0)._2, aa(0)._1.ttag)
pair with path dependent type, you can type cast as following code shows:
import languageFeature.existentials
object TestExistential {
def main(args: Array[String]): Unit = {
val aa: Array[(Animal[T], T) forSome {type T}] = Array((Dog, 5:Integer), (Cat, "stringgg"), (Dog, 2:Integer))
aa.foreach(p=>{
val ani = p._1
val attr = p._2 // compiler weakness: existential type T is not unify with ani.castType
assert(ani.attrTyp.isAssignableFrom(attr.getClass))// because of boxing, real type is Integer not Int
assert(ani.clzTyp.isAssignableFrom(ani.getClass))
val typedAni:ani.castType = ani.asInstanceOf[ani.castType]
println(s"$typedAni of type Animal[${ani.attrTyp}] with $attr")
})
}
abstract class Animal[T]{
type castType = Animal[T]
val attrTyp: Class[T]
val clzTyp: Class[castType]
}
case object Dog extends Animal[Integer] {
override val attrTyp: Class[Integer] = classOf[Integer]
override val clzTyp: Class[Dog.castType] = classOf[Dog.castType]
}
case object Cat extends Animal[String] {
override val attrTyp: Class[String] = classOf[String]
override val clzTyp: Class[Cat.castType] = classOf[Cat.castType]
}
}
if typing in scala repl, you can see the reply:
scala> val typedAni:ani.castType = ani.asInstanceOf[ani.castType]
typedAni: ani.castType = Dog
scala> typedAni
res0: ani.castType = Dog

Scala reflection with TypeTags and singleton types

I've just started experimenting with the reflection API introduced in Scala 2.10 and would expect the code below to evaluate to true five times (REPL).
Unfortunately, only the first and last expressions really do. Can somebody explain why this is the case? It seems from the compiler's perspective all these type comparisons are ok or am I getting this wrong?
Is there a way to make this (at least one .type comparison) work?
import scala.reflect.runtime.universe._
class Test[A:TypeTag](val a:A) {
val value:this.type=this
def t1:TypeTag[Test[A]]=typeTag[Test[A]]
def t2:TypeTag[this.type]=typeTag[this.type]
def t3:TypeTag[_<:Test[A]]=typeTag[this.type]
}
val a:Test[String]=new Test("a")
a.t1.tpe<:<typeOf[Test[String]] //works as expected
a.t2.tpe<:<typeOf[Test[String]] //FAILS
a.t3.tpe<:<typeOf[Test[String]] //FAILS
a.t2.tpe<:<typeOf[a.type] //FAILS
typeOf[a.type]<:<typeOf[a.type] //this works again
Tested with Scala REPL 2.10.3 and 2.11.0-M7.
Regards,
Messi
Your class doesn't know its type parameter, apparently. It may be a bug that your t2 method isn't working.
The spec says
A singleton type p .type conforms to the type of the path p.
That's kind of still true here, in so far as Test is just a Test[A]. But since the tag of A is available, you'd think it would use it.
scala> typeTag[a.type].tpe
res8: reflect.runtime.universe.Type = a.type
scala> typeTag[a.type].tpe.widen
res9: reflect.runtime.universe.Type = Test[String]
scala> typeTag[a.type].tpe.widen <:< typeOf[Test[String]]
res10: Boolean = true
scala> typeTag[a.type].tpe <:< typeOf[Test[String]]
res11: Boolean = true
scala> a.t2.tpe
res12: reflect.runtime.universe.Type = Test.this.type
scala> a.t2.tpe.widen
res13: reflect.runtime.universe.Type = Test[A]
The essential fact to remember here is that singleton types are not associated with objects (concrete instances). Rather, they're associated with identifiers.
This means that a single object can have multiple singleton types depending on what identifier it is assigned to. For example:
class C {
val self = this
val thistpe = typeOf[this.type]
type T1 = this.type
type T2 = self.type
}
val c1 = new C
val c2 = c1
val c3: c1.type = c1
val tpe1 = typeOf[c1.type]
val tpe2 = typeOf[c2.type]
val tpe3 = typeOf[c3.type]
val tpe4 = typeOf[c1.T1]
val tpe5 = typeOf[c1.T2]
val tpe6 = c1.thistpe
In the snippet above, tpe1, tpe3 and tpe4 will will be recognized as the same types, but the others won't.
In your case, you could try something like this instead:
class C {
def thisTpe(implicit tag: TypeTag[this.type]) = tag.tpe
}
val c = new C
c.thisTpe =:= typeOf[c.type] // yields true

Why is it looking for String?

Given the following code:
abstract class Field {
type T
val data: List[T]
def sum: T = data(0) + data(1)
}
I get an error on the last line - def sum: T = data(0) + data(1):
types2.scala:6: error: type mismatch;
found : Field.this.T
required: String
def sum: T = data(0) + data(1)
^
That is, it expects data(1) to be a String.
I dont understand why... (scala 2.8.1)
Your explanation will be much appreciated!
Since T does not support an addition operation, compiler assumes + to be a string concatenation operation. The following line I tried out at REPL indicates so:
scala> implicitly[Any => {def +(s: String): String}]
res16: (Any) => AnyRef{def +(s: String): String} = <function1>
What you can do is require that T have a Semigroup algebra defined. (A type is a semigroup if it supports an associative append operation.)
scala> import scalaz._
import scalaz._
scala> import Scalaz._
import Scalaz._
scala> abstract class Field[A : Semigroup] {
| val data: IndexedSeq[A]
| def sum: A = data(0) |+| data(1)
| }
defined class Field
scala> val f = new Field[Int] {
| val data = IndexedSeq(2, 3, 4)
| }
f: Field[Int] = $anon$1#d1fd51
scala> f.sum
res12: Int = 5
I replaced abstract type by a type parameter simply because I do not know how to put a context bound on an abstract type. I also changed type of data from List[A] to IndexedSeq[A] because as the name indicates indexed sequences are more suitable for indexed access than lists (which is what you do in your sum method). And finally, |+| is the semigroup append operation. For numeric types it will perform addition. For sequences, concatenation etc.
As a complement to #missingfactor's answer, while in principle I would very much favor Semigroup, there is a trait Numeric in the standard library which would do the same. And on collections whose content is Numeric (where a "Numeric structure" exists for the elements' type), you can simply call collection.sum (should you want to sum all the elements rather than the two first ones).
I prefer Semigroup for two reasons. First Numeric is much more than what is needed here, second, what are the exact properties of a Numeric structure is not clear. On the other hand, even someone not familiar with basic algebra will have a reasonable understanding of what Numeric means.
So if you are afraid of scalaz and/or semigroups, you can replace Semigroup with Numeric and |+| with +. You must import Numeric.Implicits._ so that + is available.
The compiler doesn't know how to invoke + in your type T, because it knows nothing about T. The only solution to compile this + is then a pimped string concatenation (by means of the implicit Predef.any2stringadd), which expects a string as second argument — hence the error you're getting.
After a lot of playing with this, I came up with a very simple solution.
Here is the full program
package manytypes
abstract class Field {
type T
val data: List[T]
def add (a: T, b: T): T
}
abstract class FieldInt extends Field {
type T = Int
def add (a: T, b: T): T = a + b
}
abstract class FieldDouble extends Field {
type T = Double
def add (a: T, b: T): T = a + b
}
abstract class FieldString extends Field {
type T = String
def add (a: T, b: T): T = a + b
}
object A extends App {
val ints: Field = new FieldInt { val data = List(1, 2, 3)}
val doubles: Field = new FieldDouble { val data = List(1.2, 2.3, 3.4) }
val strings: Field = new FieldString { val data = List("hello ", "this is ", "a list ")}
val fields: List[Field] = List(ints, doubles, strings)
for (field <- fields) println(field.data.reduceLeft(field.add(_, _)))
}

What is the Scala identifier "implicitly"?

I have seen a function named implicitly used in Scala examples. What is it, and how is it used?
Example here:
scala> sealed trait Foo[T] { def apply(list : List[T]) : Unit }; object Foo {
| implicit def stringImpl = new Foo[String] {
| def apply(list : List[String]) = println("String")
| }
| implicit def intImpl = new Foo[Int] {
| def apply(list : List[Int]) = println("Int")
| }
| } ; def foo[A : Foo](x : List[A]) = implicitly[Foo[A]].apply(x)
defined trait Foo
defined module Foo
foo: [A](x: List[A])(implicit evidence$1: Foo[A])Unit
scala> foo(1)
<console>:8: error: type mismatch;
found : Int(1)
required: List[?]
foo(1)
^
scala> foo(List(1,2,3))
Int
scala> foo(List("a","b","c"))
String
scala> foo(List(1.0))
<console>:8: error: could not find implicit value for evidence parameter of type
Foo[Double]
foo(List(1.0))
^
Note that we have to write implicitly[Foo[A]].apply(x) since the compiler thinks that implicitly[Foo[A]](x) means that we call implicitly with parameters.
Also see How to investigate objects/types/etc. from Scala REPL? and Where does Scala look for implicits?
implicitly is avaliable in Scala 2.8 and is defined in Predef as:
def implicitly[T](implicit e: T): T = e
It is commonly used to check if an implicit value of type T is available and return it if such is the case.
Simple example from retronym's presentation:
scala> implicit val a = "test" // define an implicit value of type String
a: java.lang.String = test
scala> val b = implicitly[String] // search for an implicit value of type String and assign it to b
b: String = test
scala> val c = implicitly[Int] // search for an implicit value of type Int and assign it to c
<console>:6: error: could not find implicit value for parameter e: Int
val c = implicitly[Int]
^
Here are a few reasons to use the delightfully simple method implicitly.
To understand/troubleshoot Implicit Views
An Implicit View can be triggered when the prefix of a selection (consider for example, the.prefix.selection(args) does not contain a member selection that is applicable to args (even after trying to convert args with Implicit Views). In this case, the compiler looks for implicit members, locally defined in the current or enclosing scopes, inherited, or imported, that are either Functions from the type of that the.prefix to a type with selection defined, or equivalent implicit methods.
scala> 1.min(2) // Int doesn't have min defined, where did that come from?
res21: Int = 1
scala> implicitly[Int => { def min(i: Int): Any }]
res22: (Int) => AnyRef{def min(i: Int): Any} = <function1>
scala> res22(1) //
res23: AnyRef{def min(i: Int): Int} = 1
scala> .getClass
res24: java.lang.Class[_] = class scala.runtime.RichInt
Implicit Views can also be triggered when an expression does not conform to the Expected Type, as below:
scala> 1: scala.runtime.RichInt
res25: scala.runtime.RichInt = 1
Here the compiler looks for this function:
scala> implicitly[Int => scala.runtime.RichInt]
res26: (Int) => scala.runtime.RichInt = <function1>
Accessing an Implicit Parameter Introduced by a Context Bound
Implicit parameters are arguably a more important feature of Scala than Implicit Views. They support the type class pattern. The standard library uses this in a few places -- see scala.Ordering and how it is used in SeqLike#sorted. Implicit Parameters are also used to pass Array manifests, and CanBuildFrom instances.
Scala 2.8 allows a shorthand syntax for implicit parameters, called Context Bounds. Briefly, a method with a type parameter A that requires an implicit parameter of type M[A]:
def foo[A](implicit ma: M[A])
can be rewritten as:
def foo[A: M]
But what's the point of passing the implicit parameter but not naming it? How can this be useful when implementing the method foo?
Often, the implicit parameter need not be referred to directly, it will be tunneled through as an implicit argument to another method that is called. If it is needed, you can still retain the terse method signature with the Context Bound, and call implicitly to materialize the value:
def foo[A: M] = {
val ma = implicitly[M[A]]
}
Passing a subset of implicit parameters explicitly
Suppose you are calling a method that pretty prints a person, using a type class based approach:
trait Show[T] { def show(t: T): String }
object Show {
implicit def IntShow: Show[Int] = new Show[Int] { def show(i: Int) = i.toString }
implicit def StringShow: Show[String] = new Show[String] { def show(s: String) = s }
def ShoutyStringShow: Show[String] = new Show[String] { def show(s: String) = s.toUpperCase }
}
case class Person(name: String, age: Int)
object Person {
implicit def PersonShow(implicit si: Show[Int], ss: Show[String]): Show[Person] = new Show[Person] {
def show(p: Person) = "Person(name=" + ss.show(p.name) + ", age=" + si.show(p.age) + ")"
}
}
val p = Person("bob", 25)
implicitly[Show[Person]].show(p)
What if we want to change the way that the name is output? We can explicitly call PersonShow, explicitly pass an alternative Show[String], but we want the compiler to pass the Show[Int].
Person.PersonShow(si = implicitly, ss = Show.ShoutyStringShow).show(p)
Starting Scala 3 implicitly has been replaced with improved summon which has the advantage of being able to return a more precise type than asked for
The summon method corresponds to implicitly in Scala 2. It is
precisely the same as the the method in Shapeless. The difference
between summon (or the) and implicitly is that summon can return a
more precise type than the type that was asked for.
For example given the following type
trait F[In]:
type Out
def f(v: Int): Out
given F[Int] with
type Out = String
def f(v: Int): String = v.toString
implicitly method would summon a term with erased type member Out
scala> implicitly[F[Int]]
val res5: F[Int] = given_F_Int$#7d0e5fbb
scala> implicitly[res5.Out =:= String]
1 |implicitly[res5.Out =:= String]
| ^
| Cannot prove that res5.Out =:= String.
scala> val x: res5.Out = ""
1 |val x: res5.Out = ""
| ^^
| Found: ("" : String)
| Required: res5.Out
In order to recover the type member we would have to refer to it explicitly which defeats the purpose of having the type member instead of type parameter
scala> implicitly[F[Int] { type Out = String }]
val res6: F[Int]{Out = String} = given_F_Int$#7d0e5fbb
scala> implicitly[res6.Out =:= String]
val res7: res6.Out =:= String = generalized constraint
However summon defined as
def summon[T](using inline x: T): x.type = x
does not suffer from this problem
scala> summon[F[Int]]
val res8: given_F_Int.type = given_F_Int$#7d0e5fbb
scala> summon[res8.Out =:= String]
val res9: String =:= String = generalized constraint
scala> val x: res8.Out = ""
val x: res8.Out = ""
where we see type member type Out = String did not get erased even though we only asked for F[Int] and not F[Int] { type Out = String }. This can prove particularly relevant when chaining dependently typed functions:
The type summoned by implicitly has no Out type member. For this
reason, we should avoid implicitly when working with dependently typed
functions.
A "teach you to fish" answer is to use the alphabetic member index currently available in the Scaladoc nightlies. The letters (and the #, for non-alphabetic names) at the top of the package / class pane are links to the index for member names beginning with that letter (across all classes). If you choose I, e.g., you'll find the implicitly entry with one occurrence, in Predef, which you can visit from the link there.