Published 2013-09-18.
Last modified 2016-10-26.
Time to read: 6 minutes.
Implicit conversions provide extra functionality to value classes.
The sample code for this lecture can be found in
courseNotes/
.
Implicit methods allow an instance of a type to be viewed as if it were another type. Implicit methods provide implicit conversions.
Using the example from the previous lecture, we can write implicit converters between
Int
and Multiplier3
, and Int
and Divider3
.
@implicitNotFound("Cannot find implicit of type Multiplier3 in scope") case class Multiplier3(value: Int) extends AnyVal
@implicitNotFound("Cannot find implicit of type Divider3 in scope") case class Divider3(value: Int) extends AnyVal
object ImplicitConversions extends App { implicit val defaultMultiplier = Multiplier3(2)
implicit val defaultDivider = Divider3(3)
def multiply(value: Int)(implicit multiplier: Multiplier3): Int = value * multiplier.value
def divide(value: Int)(implicit divider: Divider3): Int = value / divider.value
implicit def intToMultiplier(int: Int) = Multiplier3(int)
implicit def intToDivider(int: Int) = Divider3(int)
println(s"multiply(2)(3)=${multiply(2)(3)}") println(s"multiply(5)=${multiply(5)}") println(s"divide(12)(4)=${divide(12)(4)}") println(s"divide(9)=${divide(9)}") }
intToMultiplier and intToDivider
are implicitly called when the Int
values highlighted in orange (3 and 4)
need to be converted into Multiplier3
or Divider3
instances.
Because these methods are called implicitly, their names do not appear anywhere in the program except where they are defined.
Note that the original Int
values (3 and 4) are not actually changed;
instead, the implicit methods generate new Multiplier3
or Divider3
values from the original Int
values,
and the new values are passed as parameters to the multiply
or divide
methods.
Output is:
multiply(2)(3)=6 multiply(5)=10 divide(12)(4)=3 divide(9)=3
You can run the code as follows:
$ sbt "run-main ImplicitConversions"
Implicit methods can be defined in classes, objects and traits.
Implicit Resolution Rules
The previous lecture described where the Scala compiler looks for implicit values. The compiler uses the following rules to resolve implicit values and functions.
- Decoration – Properties and methods must be decorated with
implicit
in order to be considered for resolution by the compiler. -
Scope – The compiler only considers the implicits currently in scope as a single identifier for resolution.
Properties of an implicit object are not considered, unless they are also marked as an
implicit
.Scala codeimplicit object Blah { implicit val yesMe: Boolean = true val notMe: Boolean = false }
- One at a time – Only one implicit is tried at a time to resolve - implicits do not normally chain.
- Explicits first – if a value or function is explicitly provided, then implicits are not used.
- Only One in Scope - If there are two applicable implicits in the same scope, the compiler will issue an error rather than pick one at random.
Implicit Scope Management
It is often helpful to define implicits in a package object.
We discussed package objects in the
Scala Imports and Packages lecture of the
Introduction to Scala course.
This makes accessing the implicit easier.
The code below uses a trick to define the implicit converter stringToYeller
in the yeller
package object.
package yeller { case class Yeller(s: String) { def yell: String = s.toUpperCase + "!!" }
object `package` { implicit def stringToYeller(s: String): Yeller = Yeller(s) } }
object YellerMain extends App { import yeller._
println("Look out".yell) }
Notice the backticks that surround the word `package`
.
This causes the word package
to be considered as an object name instead of a Scala keyword.
You can place backticks around otherwise illegal package and variable names to force them to be evaluated as names.
The result is that stringToYeller
is defined in the yeller
package object, which is imported into YellerMain
by import yeller._
.
Because the implicit converter stringToYeller
is now in scope, strings in the YellerMain
object that have an otherwise illegal method invoked are automatically converted to Yeller instances as required.
This allows us to write "Look out".yell
.
You can run this program as follows:
$ sbt "runMain YellerMain" LOOK OUT!!
Exercise
- Rewrite
YellerMain
so that it is more efficient by using value classes. - Add a
whisper
method that forcesString
s to lower case, and prefaces them with "Shhh!
"
Solution
This solution is provided as solutions.EfficientYeller
.
package solutions
case class Yeller(val s: String) extends AnyVal { def yell: String = s.toUpperCase + "!!" def whisper: String = "Shhh! " + s.toLowerCase }
object `package` { implicit def stringToYeller(s: String): Yeller = Yeller(s) }
object EfficientYeller extends App { println("Look out".yell) println("This is a secret".whisper) }
You can run this solution by typing:
scala> sbt "runMain solutions.EfficientYeller" LOOK OUT!! Shhh! this is a secret
Default Values for Implicit Parameters
You can specify default values for implicit parameters. This can be a source of difficult-to-find bugs. I recommend that you do not do this.
scala> def asdf(implicit x: Int=3): Unit = println(x) asdf: (implicit x: Int)Unit
scala> implicit val y=2 y: Int = 2
scala> asdf() 3
You can run this code as follows.
$ sbt "runMain ImplicitDefaultValues"
Coercion by Implicit Conversions
As you know, coercion is what a compiler of a typed language does when converting an argument or an operand to the type expected by a function or an operator. As we have already seen, Scala supports conversion through implicits. Here is an example:
In the Either, Left and Right lecture of the
Introduction to Scala course we defined an
Either[NonLivingThing, LivingThing]
and assigned it a value, like this:
scala> case class LivingThing(name: String, species: String) defined class LivingThing
scala> case class NonLivingThing(name: String, description: String) defined class NonLivingThing
scala> val thing1: Either[NonLivingThing, LivingThing] = Right(LivingThing("Leatherback Turtle", "Dermochelys coriacea")) thing1: Either[NonLivingThing,LivingThing] = Right(LivingThing(Leatherback Turtle,Dermochelys coriacea))
In that lecture I mentioned that the Scala compiler is not smart enough to figure out that a LivingThing
belongs on the Right
.
scala> val thing1: Either[NonLivingThing, LivingThing] = LivingThing("Leatherback Turtle", "Dermochelys coriacea") <console>:15: error: type mismatch; found : LivingThing required: Either[NonLivingThing,LivingThing] val thing1: Either[NonLivingThing, LivingThing] = LivingThing("Leatherback Turtle", "Dermochelys coriacea")
We could define an implicit conversion to simplify our code, however.
scala> import scala.language.implicitConversions import scala.language.implicitConversions
scala> implicit def livingToRight(thing: LivingThing): Right[NonLivingThing, LivingThing] = Right(thing) livingToRight: (thing: LivingThing)Right[NonLivingThing,LivingThing]
Now the error message goes away:
scala> val thing1: Either[NonLivingThing, LivingThing] = LivingThing("Leatherback Turtle", "Dermochelys coriacea") thing1: Either[NonLivingThing,LivingThing] = Right(LivingThing(Leatherback Turtle,Dermochelys coriacea))
Another Example
case class Complex(re: Double, im: Double) { def +(that: Complex): Complex = Complex(re + that.re, im + that.im)
def -(that: Complex): Complex = Complex(re - that.re, im - that.im)
override def toString = s"$re + ${im}i" }
implicit def doubleToComplex(d: Double): Complex = Complex(d, 0)
Let’s implicitly use the method doubleToComplex
to convert a Double
instance into a Complex
instance,
so we can add it to another Complex
instance.
scala> Complex(2.0, 5.0) + 5.0 res8: Complex = 7.0 + 5.0i
scala> 5.0 + Complex(1.0, -2.0) res9: Complex = 6.0 + -2.0i
You can run this code as follows:
$ sbt "runMain ImplicitCoercion"
If you view line 24 of ImplicitCoercion.scala
in IntelliJ IDEA, you will notice that the number 5.0 is underlined in gray.
IntelliJ IDEA underlines values and variables in gray that are subject to implicit conversions.
This is the line:
println(s"""Complex(2, 5) + 5.0 = ${Complex(2, 5) + 5.0}""")
Click on 5.0, then press Ctrl-Shift-Q.
This shows the implicits that are in scope which are candidates for conversion, and highlights the best match used by the compiler.

This means the occurrence of 5.0 on line 24 is implicitly converted to Complex(5.0, 0.0) by doubleToComplex.
Exercise – Convert Tuples to Complex
Extend the ImplicitCoercion
program so Tuple2
s of Int
s, Float
s, Double
s
and all 9 combinations thereof can be added and subtracted with Complex
instances.
Assume that the first property of a tuple is the real part, and the second property is the imaginary part.
Hint
As discussed in the previous course, you could use the special notation for Tuple2
.
However, your program will read better if you do not.
Solution
package solutions
object ImplicitCoercion extends App { case class Complex(re: Double, im: Double) { def +(that: Complex): Complex = Complex(re + that.re, im + that.im)
def -(that: Complex): Complex = Complex(this.re - that.re, this.im - that.im)
override def toString = s"$re + ${im}i" }
implicit def doubleToComplex(d: Double): Complex = Complex(d, 0)
implicit def tupleToComplex1(t: (Int, Int)) = Complex(t._1, t._2) implicit def tupleToComplex2(t: (Int, Float)) = Complex(t._1, t._2) implicit def tupleToComplex3(t: (Float, Int)) = Complex(t._1, t._2) implicit def tupleToComplex4(t: (Float, Float)) = Complex(t._1, t._2) implicit def tupleToComplex5(t: (Int, Double)) = Complex(t._1, t._2) implicit def tupleToComplex6(t: (Double, Int)) = Complex(t._1, t._2) implicit def tupleToComplex7(t: (Double, Double)) = Complex(t._1, t._2) implicit def tupleToComplex8(t: (Float, Double)) = Complex(t._1, t._2) implicit def tupleToComplex9(t: (Double, Float)) = Complex(t._1, t._2)
println(s"""Complex(2, 5) + 5.0 = ${Complex(2, 5) + 5.0}""") println(s"""5.0 + Complex(1, -2) = ${5.0 + Complex(1, -2)}""")
println(s"""Complex(2, 5) + (2f, 5) = ${Complex(2, 5) + (2f, 5)}""") println(s"""Complex(2, 5) + (2, 5f) = ${Complex(2, 5) + (2, 5f)}""") println(s"""Complex(2, 5) + (2f, 5f) = ${Complex(2, 5) + (2f, 5f)}""")
println(s"""Complex(2, 5) + (2d, 5) = ${Complex(2, 5) + (2d, 5)}""") println(s"""Complex(2, 5) + (2, 5d) = ${Complex(2, 5) + (2, 5d)}""") println(s"""Complex(2, 5) + (2d, 5d) = ${Complex(2, 5) + (2d, 5d)}""")
println(s"""Complex(2, 5) + (2f, 5d) = ${Complex(2, 5) + (2f, 5d)}""") println(s"""Complex(2, 5) + (2d, 5f) = ${Complex(2, 5) + (2d, 5f)}""") println(s"""Complex(2, 5) + (2d, 5d) = ${Complex(2, 5) + (2d, 5d)}""") }
You can run this solution by typing:
$ sbt "runMain solutions.ImplicitCoercion" Complex(2, 5) + 5.0 = 7.0 + 5.0i 5.0 + Complex(1, -2) = 6.0 + -2.0i Complex(2, 5) + (2f, 5) = 4.0 + 10.0i Complex(2, 5) + (2, 5f) = 4.0 + 10.0i Complex(2, 5) + (2f, 5f) = 4.0 + 10.0i Complex(2, 5) + (2d, 5) = 4.0 + 10.0i Complex(2, 5) + (2, 5d) = 4.0 + 10.0i Complex(2, 5) + (2d, 5d) = 4.0 + 10.0i Complex(2, 5) + (2f, 5d) = 4.0 + 10.0i Complex(2, 5) + (2d, 5f) = 4.0 + 10.0i Complex(2, 5) + (2d, 5d) = 4.0 + 10.0i
Implicit Search Order
This section contains a more detailed explanation of where the Scala compiler looks for implicit values and converters.
-
Implicits defined in the current scope bind first.
The package object is part of the current scope.
Scala code
object InnerScope { implicit val list2 = List(1, 2, 3)
def res(implicit list: List[Int]): List[Int] = list }
object OuterScope extends App { implicit val list = List(1, 2)
println(InnerScope.res) }To run this program, type:
Shell$ sbt "runMain OuterScope" List(1, 2)
-
If an implicit of the required type is not found in the current scope or parent scope, the Scala compiler then searches imports for an implicit declaration of the required type.
Scala code
object InnerScope { implicit val list2 = List(1, 2, 3)
def res(implicit list: List[Int]): List[Int] = list }
object ImportedImplicit extends App { import InnerScope._
println(res) }To run this program, type:
Shell$ sbt "runMain ImportedImplicit" List(1, 2, 3)
-
The Scala compiler then looks in companion objects for implicits:
Shell
object CompanionScope extends App { class A(val n: Int) { def +(other: A) = new A(n + other.n) }
object A { implicit def fromInt(n: Int): A = new A(n) }
val x = 1 + new A(1) // is converted into: val y = A.fromInt(1) + new A(1)
println(s"x.n=${x.n}") println(s"y.n=${y.n}") }To run this, type:
Shell$ sbt "runMain CompanionScope" x.n=2 y.n=2
Here is an excellent article on the subject.
I provide a modified version of the code in ImplicitFun.scala
in the courseNotes
project.
Predef.scala
The source code for the Scala runtime library includes
Predef.scala
,
which defines type aliases and many implicit conversion methods.
These definitions are automatically imported into every Scala program.
Predef provides many implicit conversions which convert from a value type, such as Int
or String
,
to an enhancing type, such as RichInt
and
WrappedString
.
Predef.scala
also defines a useful method called
require
,
which has the following signature:
final def require(requirement: Boolean, message: => Any): Unit
require
tests an expression, throwing an IllegalArgumentException
if false
.
This method is similar to
assert
,
but blames the caller of the method for violating the condition.
I encourage you to read the source code for Predef.scala.
REPL :implicits
The Scala REPL’s :implicits
command displays all the implicits in scope.
Unless you add the -v
switch, it does not display the implicit conversions defined in Predef.scala
.
scala> :implicits No implicits have been imported other than those in Predef.
scala> :implicits -v /* 64 implicit members imported from scala.Predef */ /* 6 inherited from scala */ final implicit class ArrayCharSequence extends final implicit class ArrowAssoc extends final implicit class Ensuring extends final implicit class SeqCharSequence extends final implicit class StringFormat extends final implicit class any2stringadd extends
/* 37 inherited from scala.Predef */ final implicit def ArrowAssoc[A](self: A): ArrowAssoc[A] final implicit def Ensuring[A](self: A): Ensuring[A] final implicit def StringFormat[A](self: A): StringFormat[A] final implicit def any2stringadd[A](self: A): any2stringadd[A] implicit def booleanArrayOps(xs: Array[Boolean]): scala.collection.ArrayOps[Boolean] implicit def byteArrayOps(xs: Array[Byte]): scala.collection.ArrayOps[Byte] implicit def charArrayOps(xs: Array[Char]): scala.collection.ArrayOps[Char] implicit def doubleArrayOps(xs: Array[Double]): scala.collection.ArrayOps[Double] implicit def floatArrayOps(xs: Array[Float]): scala.collection.ArrayOps[Float] implicit def genericArrayOps[T](xs: Array[T]): scala.collection.ArrayOps[T] implicit def intArrayOps(xs: Array[Int]): scala.collection.ArrayOps[Int] implicit def longArrayOps(xs: Array[Long]): scala.collection.ArrayOps[Long] implicit def refArrayOps[T <: AnyRef](xs: Array[T]): scala.collection.ArrayOps[T] implicit def shortArrayOps(xs: Array[Short]): scala.collection.ArrayOps[Short] implicit def unitArrayOps(xs: Array[Unit]): scala.collection.ArrayOps[Unit]
implicit def $conforms[A]: A => A final implicit def ArrayCharSequence(arrayOfChars: Array[Char]): ArrayCharSequence implicit def Boolean2boolean(x: Boolean): Boolean implicit def Byte2byte(x: Byte): Byte implicit def Character2char(x: Character): Char implicit def Double2double(x: Double): Double implicit def Float2float(x: Float): Float implicit def Integer2int(x: Integer): Int implicit def Long2long(x: Long): Long final implicit def SeqCharSequence(sequenceOfChars: scala.collection.IndexedSeq[Char]): SeqCharSequence implicit def Short2short(x: Short): Short implicit def augmentString(x: String): scala.collection.StringOps implicit def boolean2Boolean(x: Boolean): Boolean implicit def byte2Byte(x: Byte): Byte implicit def char2Character(x: Char): Character implicit def double2Double(x: Double): Double implicit def float2Float(x: Float): Float implicit def int2Integer(x: Int): Integer implicit def long2Long(x: Long): Long implicit def short2Short(x: Short): Short implicit def tuple2ToZippedOps[T1, T2](x: (T1, T2)): runtime.Tuple2Zipped.Ops[T1,T2] implicit def tuple3ToZippedOps[T1, T2, T3](x: (T1, T2, T3)): runtime.Tuple3Zipped.Ops[T1,T2,T3]
/* 20 inherited from scala.LowPriorityImplicits */ implicit def booleanWrapper(x: Boolean): runtime.RichBoolean implicit def byteWrapper(x: Byte): runtime.RichByte implicit def charWrapper(c: Char): runtime.RichChar implicit def doubleWrapper(x: Double): runtime.RichDouble implicit def floatWrapper(x: Float): runtime.RichFloat implicit def genericWrapArray[T](xs: Array[T]): mutable.ArraySeq[T] implicit def intWrapper(x: Int): runtime.RichInt implicit def longWrapper(x: Long): runtime.RichLong implicit def shortWrapper(x: Short): runtime.RichShort implicit def wrapBooleanArray(xs: Array[Boolean]): mutable.ArraySeq.ofBoolean implicit def wrapByteArray(xs: Array[Byte]): mutable.ArraySeq.ofByte implicit def wrapCharArray(xs: Array[Char]): mutable.ArraySeq.ofChar implicit def wrapDoubleArray(xs: Array[Double]): mutable.ArraySeq.ofDouble implicit def wrapFloatArray(xs: Array[Float]): mutable.ArraySeq.ofFloat implicit def wrapIntArray(xs: Array[Int]): mutable.ArraySeq.ofInt implicit def wrapLongArray(xs: Array[Long]): mutable.ArraySeq.ofLong implicit def wrapRefArray[T <: AnyRef](xs: Array[T]): mutable.ArraySeq.ofRef[T] implicit def wrapShortArray(xs: Array[Short]): mutable.ArraySeq.ofShort implicit def wrapString(s: String): immutable.WrappedString implicit def wrapUnitArray(xs: Array[Unit]): mutable.ArraySeq.ofUnit
/* 1 inherited from scala.LowPriorityImplicits2 */ implicit def copyArrayToImmutableIndexedSeq[T](xs: Array[T]): IndexedSeq[T]
Remember that all of the implicit conversions are defined as methods, but Scala lifts all of them into functions.
(We discussed method ’lifting’ in the
Introduction to Scala course.)
This is only important when you want to use implicitly
to discover the implicit converter in scope.
Discovering the Current Implicit Conversion In Scope with implicitly
Sometimes you need to access the implicit function that converts between two types.
The implicitly
method, defined in Predef
, can check if an implicit converter of a given type is available and return it if so.
For example, Int
can be implicitly converted to Long
, a
s you can see in the
type hierarchy diagram for Int
(click on "Type Hierarchy").

We can use the implicitly
method in the REPL to discover the function that performs the implicit conversion from Int
to Long
.
scala> val i2l = implicitly[Function[Int, Long]] i2l: Int => Long = <function1>
scala> i2l(3) res10: Long = 3
We can use an alternative syntax to obtain the same implicit conversion function, and then its apply
method is invoked while passing in 5,
so the result 5L
can be computed.
scala> implicitly[Int => Long].apply(5) res11: Long = 5
This code can be run as follows:
$ sbt "runMain ImplicitlyConversion"
Methods as Implicit Values

This technique provides controlled conversions between types where the values are all implicitly known.
This example uses the Multipler
class and the multiply
method from the
Implicit Values lecture.
Here they are again for your convenience:
scala> case class Multiplier(value: Int) defined class Multiplier
scala> %}def multiply(value: Int)(implicit multiplier: Multiplier): Int = value * multiplier.value multiply: (value: Int)(implicit multiplier: Multiplier)Int
A method may be used as an implicit argument, however it must not take any arguments itself, unless those arguments are implicit. That’s because when the implicit method is used and substituted as the missing parameter, there is no way to pass parameters to it, unless those parameters can themselves be found implicitly.
To see this in action, let’s introduce a Facto
class and an implicit conversion from
r
Factor
to Multiplier
called factorToMultiplier
that accepts an implicit Factor
.
scala> case class Factor(value: Int) defined class Factor
scala> implicit def factorToMultiplier(implicit factor: Factor): Multiplier = Multiplier(factor.value) factorToInt: (implicit factor: Factor)Int
Now we’ll create an implicit instance of Factor
.
scala> implicit val defaultFactor = Factor(3) defaultFactor: Factor = Factor(3)
The test
method shown next is just to demonstrate that if a method is invoked that accepts an implicit parameter,
but no value is supplied for that parameter, and there is no implicit value of exactly the right type in scope
(because there is no implicit Multiplier
in scope),
the Scala compiler will search for another implicit value that can be converted to the desired type of the implicit parameter.
In this case, the implicit defaultFactor
can implicitly be converted to a Multiplier
by the
implicit factorToMultiplier
method that is in scope.
scala> def test(implicit m: Multiplier) = println(m) test: (implicit m: Multiplier)Unit
scala> test Multiplier(3)
The same conversion is performed for the multiply
method’s second (implicit) parameter list.
We implicitly invoke the factorToMultiplier
method, which causes the Factor
instance in scope
to be converted to a Multiplier
, which is then implicitly passed to the second parameter list of multiply
.
scala> val y = multiply(3) y: Int = 9
You can run this code example from the command line by typing:
$ sbt "runMain MethodsImplicitValues" ... lots of output ... result=9
© Copyright 1994-2024 Michael Slinn. All rights reserved.
If you would like to request to use this copyright-protected work in any manner,
please send an email.
This website was made using Jekyll and Mike Slinn’s Jekyll Plugins.