To Thine Own Self Be True

When my ridiculously bad dates started pouring out the edges of my fingertips, clacking on to my keyboard and then mysteriously showing up on the inter-webs (not so mysterious, I suppose, when you…

Smartphone

独家优惠奖金 100% 高达 1 BTC + 180 免费旋转




Being Explicit on Scala Implicits

Implicits are used for various critical purposes in Scala.
In English, an implicit is something that suggested or implied though not directly expressed; and as most programming languages — that derive concepts from life — Scala too professes the same use cases for the use of the keyword implicit.

What if we didn’t have to repeatedly pass variables to functions? What if the function could just understand based on the context? Implicit parameters allow you do this.

Let’s take a look at this function that formats a letter based on the parameters passed to it.

Wouldn’t it be great if the function just knew who was writing the letter implicitly ?
Scala supports multiple parameter list and the implicit prefix in function definitions, such that we can rewrite the above function to:

The implicit parameters to the function call are looked up by type of the parameter. The compiler looks for suitable variables that are defined as implicit in the scope of the function call. This also means that only one implicit should be defined for a particular type in that scope.

Problematic scenarios

With implicits there are two scenarios for errors when no variable is explicitly mentioned in the function call:

Implicit parameters are useful to avoid a lot of boilerplate parameter passing and can make your code more readable. So if you see yourself passing the same parameters several times in quick succession, then you could use implicit to reduce the verbosity and replications.
The above examples are just contrived for an explanation, those are definitely not how implicits should be used.

We can also define an implicit function that the compiler uses when it feels it is appropriate and intended. When the compiler notices that a type is not what is expected in the execution context it searches for an implicit function that would allow it to be converted to the expected type. The Scala library uses this extensively

Let’s dive into some code to understand better:

Now very obviously here the Ints are being implicitly converted to Double. How is Scala doing this?

Below is a Snippet from the Scala Library that defines implicits in the Int.scala file.
More specifically in the Companion Object of the Int Class.

Oh, that’s right! Scala has inbuilt implicit functions defined for each of its type that allow the programmer to make use of the implicit conversions. That’s how the Int parameters I passed into the function call were implicitly converted into Double.
Here we notice that there is no implicit conversion from Int to String. Now let’s test what happens when we define a function that expects a String but receives and Int and how we can define our implicit function to enable this.

So an implicit function helps type conversion by converting from Type A to any Type B. There are no constraints to what B can be!

This is how implicit conversions are performed in Scala. The implicit function name is not as important as the signature itself. When encountering type mismatch in function calls, the compiler looks for implicit functions that would be suitable in the execution context. In our case, the compiler was looking for an implicit function with the type Int => String or Dog => Cat.

Given the knowledge of implicit parameters and implicit functions, the natural flow next would be to create a library of sorts for operations such as conversions and formatting, etc.

Let’s create a case class for String Enhancements that we will call SuperStrings, and we will provide it with the new capabilities.

What we did here is create a type and provide it with some capabilities. Then we created an implicit function to do the conversions and make use of those capabilities. The same can be done with Scala Implicit Classes. They are made for this very purpose and remove the boilerplate around adding the implicit conversions and get the same functionality in lesser lines of code.

Implicit classes that were introduced Scala 2.10 do have some limitations:

One of the most common type classes known in Scala is Ordering. (scala.math.Ordering) It is used for comparing any two instances of the same type thereby enabling other functions sorting and searching. Its implementation in Scala would look something like (Reduced in verbosity and detail)

In Scala, the sorted function on SeqLike instances has the following definition:

And hence it can be used as such:

So essentially a type class will define behavior for a particular type.
Type classes consist of three components:

Let’s build again upon the examples of cats and dogs as mentioned in earlier sections.

Now here we can assume that all behaviors that are native to cats and dogs are implemented into the class. (eg: eat, drink, sleep, purr/bark, etc)

Let’s define these creative behaviors that pets have begun to show, So I will create a trait called BehaveCreatively and provide the function signatures.

Let’s implement the type classes and provide implementations for these functions. Since only the cats and dogs have started to show these abilities we can only implement for those Pets.

Here, the object the type classes are wrapped in is not important but it’s a good idea to keep them organised.
Making the instance implicit allows me to use them better in the upcoming steps.

III A — Interface Object

This approach uses the functions in objects approach. Generally like it is done in every Utils object.

Now as a consumer of this API, I would have to use it as such:

This approach provides you with a new function which you can apply to your creative Dogs and Cats. But this also seems like too much work to create a “Utils” function for these Pets. I prefer the next approach.

III B — Interface Syntax

In this approach, after creating the type class instances you have to create the implicit class/object.

Now as a consumer of this API, I would have to use it as such:

That’s it. You have provided an implicit conversion from Dog/Cat to BehaveCreativelyOps, and hence as seen above, Dog/Cat can call those functions.
If you assume that you had no access to the original implementation of those data types, this is amazing. You just added functionality to closed class. This provides an approach that lets you add new behavior to existing classes without using traditional inheritance, especially in the case where you can’t (or don’t want to) modify the existing source code of existing data types.

Scala Implicits are valuable and complex features of the language. It’s always good to dig into the languages source code and try to find such interesting features. Having said this, the non-explicit nature of implicits makes it easy to go wrong with it. They are usually used for very specific purposes and overuse of it is generally not recommended.

Interesting finds:

Add a comment

Related posts:

UN Climate Summit reaches agreement but fails on carbon market consensus

An agreement was reached on the final hours of the UN Climate Summit (COP25) in Madrid, leaving the carbon market negotiations, the only one missing from the Paris Agreement, unresolved…

Avoid boredom and have fun in the lockdown CORONA!!!!

This blog will make you wish forever lockdown. Here are some awesome tips that will make you have fun and remember your childhood. Read a Good Book. Organise your Photo Albums. Build with Lego Almost…

A Short Meditation on Balance and Fear

There are my responsibilities as a father, being a sort of perpetual student, my desire to dedicate more time to write, spend time outdoors riding bicycles or running. Too many forces applied to my…