Implicits in Scala (2.12.2)

Oleksii Avramenko
4 min readFeb 20, 2017

--

Scala’s implicits have multiple applicable use cases which can serve different purposes. In this article we will go over some examples and try to understand how they can be useful. We will cover:

  • Implicit parameters
  • Type conversions (implicit functions)
  • “Pimp my library” (implicit classes)
  • Type classes (implicit objects)

Case 1: implicit parameters

Lets take a look at simplest example

Here bob will be implicitly passed into function greet. Missing parameters to the function call are looked up by type in the current scope meaning that code will not compile if there is no implicit variable of type String in the scope or there are multiple variables of the same type which will cause ambiguity:

I don’t think this is the indented use case for implicits and I wouldn’t recommend to use this for obvious reasons.

Case 2: Type conversions with implicit functions

Implicit functions allow us to define conversions between types:

When a compiler sees a type that is not expected in the evaluation context then it will try to find an implicit function in the current scope that can produce the expected type. In our example such contexts are expression 42.toUpperCase() and a function call functionTakingString(42). FunctiontoUpperCase() is not a defined on integers so intToStr is considered as a conversion and code compiles. The implicit function name is not that important — only the function type signature, in our case its (Int) => (String).

Case 3: “Pimp my library”

So, as we saw above, implicit function can convert some type A into type B. There is actually no constraints on the type B, it doesn’t have to be a primitive type, like in the example. Let’s say we have a simple class working on string:

We can write an implicit function that converts String into our StringOps.

That allows us to call our functions on String as if they were part of String class.

Scala 2.10 introduced implicit classes that can help us reduce the boilerplate of writing implicit function for conversion.

Note, that there are requirements for the class to be implicit:

  • It has to be inside another trait, class or object
  • It has to have exactly one parameter (but it can have multiple implicit parameters on its own)
  • There may not be any method, member or object in scope with the same name

Case 4: Type classes

With implicit objects it is possible to implement type classes — a type system construct that supports ad hoc polymorphism. (To get more understanding about type classes and their purpose check this link).

Type class is somewhat similar to an interface which can have multiple implementations. In OOP languages those implementations are usually classes that extend the interface and are instantiated where needed. With type classes they have to be instantiated once and be ‘globally’ available. Singleton is a usual name for this pattern which scala natively supports with object declarations.

Typical example of type classes application is a Monoid implementation.

Here we use implicit objects that are basically singletons which can be used in implicit parameters list. Lets take a look at “sum” function: it takes a sequence of some values and produces their sum but the “sum” can mean different things based on value types. If it’s integers then it’s just an addition, if strings — string concatenation, lists — lists concatenation. Information about which implementation to use comes in implicit parameter that is usually called “ev”. ev stands for evidence — an evidence that provided type A implements interface Monoid. It might be easier to think about evidence as a functional analogy for strategy pattern where we pass desired implementation into the function. We also doing it implicitly meaning that compiler will do all the work for you. If you don’t have an implementation for some type and you try to use it — the code won’t compile.

There is an alternative syntax for specifying implement parameters list:

Both definitions are equivalent but in the second case notation is a bit shorter. But we lost the name of an evidence (implementation) which we are referencing. There is a syntactic sugar to retrieve it — implicitly:

No magic here — implicitly is just a regular function in Predef.scala that basically takes a single implicit parameter, gives it a name and returns it. Looks like this:

Scala implicits are powerful features of the language which can be used in different context to achieve different goals. Comes without saying that because of it’s non explicit nature its easy to get things wrong so use it carefully.

--

--