What is the Scala identifier "implicitly"?
Solution 1
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)
Solution 2
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]
^
Solution 3
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 betweensummon
(or the) andimplicitly
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.
Related videos on Youtube
Comments
-
oluies almost 3 years
I have seen a function named
implicitly
used in Scala examples. What is it, and how is it used?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 thatimplicitly[Foo[A]](x)
means that we callimplicitly
with parameters.Also see How to investigate objects/types/etc. from Scala REPL? and Where does Scala look for implicits?
-
Jeff over 13 yearsOf course, those scaladocs say nothing at all about implicitly, so that hardly counts as documentation. How would someone figure out what that method does from those docs alone? I feel routinely let down by the Scala documentation. The behavior of methods like implicitly are far from obvious, and the documentation on them is barely better than nonexistent. Thank god for Stack Overflow. /end rant
-
oluies over 13 years
-
retronym over 13 yearsThe type signature documents this one pretty well.
-
davetron5000 over 13 yearsThe method doesn't exactly check; it seems to cause a compile error if there isn't an implicit value available and, if there is, seems to retrieve it. Can you provide some more context on why I'd ever want to use this?
-
retronym over 13 years
implicitly[Ordering[(Int, String)]].compare( (1, "b"), (1, "a") )
, especially to retrieve an implicit parameter introduced by a Context Bound:def foo[A: Ordering](a1: A, a2: A) = implicitly[Ordering[A]].compare(a1, a2)
-
Thomas W over 10 years
implicit
appears to be an important language-feature in Scala, and definitely worthy of proper explanation. Thinking that docs detailing only a type-signature count seems more like intellectual self-gratification, than a genuine answer. See the specific questions asked by the OP -- what is it, and how is it used? Neither answered by this, or in the nightly docs which you don't even provide an actual link to. scala-lang.org/files/archive/nightly/docs/library/… This doesn't teach anything. See Niklaus Wirth or Turbo Pascal for examples of genuine docs. -1 -
Randall Schulz about 10 years
implicit
andimplicitly
are related, but quite distinct. Theimplicit
keyword is part of the language.implicitly
is defined in plain Scala code in the standard library. Since the on-line docs include source links, I believe it's still best to refer questioners to those documents and the linked source. -
jhegedus about 10 yearsscala> 1.min(2) res0: Int = 1 In Scala 2.10.3 I get an error:scala> implicitly[Int => { def min(i: Int): Any }] <console>:8: error: No implicit view available from Int => AnyRef{def min(i: Int): Any}. implicitly[Int => { def min(i: Int): Any }]
-
emeth over 9 yearsThis answer would be updated for the latest version.
-
chaotic3quilibrium over 9 yearsTo see retronym's discussion in the video link above, skip to the point 13:50.
-
Malkaviano about 5 yearsimplicitly[Int => AnyVal{ def min(i: Int): Int }] will work. Should be fixed in the answer.