In our last blog, we have discussed the Type Class. You can find that blog Here: Type Class. Now we will discuss the Implicit in Scala.
Implicit
Implicit in Scala refers to either a value that can be passed “automatically”, so to speak or a conversion from one type to another that is made automatically. So we can create the implicit method with the help of Scala standard library because it provides generic type class interface with the name of implicitly.
We can use implicitly to fetch any value from the implicit scope. We have to provide the type and rest work is done by the implicit.
Implicitly is good to use for the debugger. We can just provide implicitly to the compiler and then the compiler will make sure to find the instance of type class and will ensure that there will not be any ambiguous implicit error. In cats, most type classes provide the other mean for fetching the instances.
Implicit Scope
Compiler searches for the instances in the implicit scope when we call it, which basically consist:
- Local or inherited definitions
- Imported definitions
- Definitions in the companion object of the type class or the parameter
If you want to wrap Definition with the implicit scope then it should be tagged with the implicit keyword. But if the compiler sees multiple candidate definitions then it will throw ambiguous implicit values.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
implicit val writer1: JsonWriter[String] = JsonWriterInstances.stringWriter | |
implicit val writer2: JsonWriter[String] = JsonWriterInstances.stringWriter | |
Json.toJson("A string") | |
<console>:27: error: ambiguous implicit values: | |
both value stringWriter in object JsonWriterInstances of type => JsonWriter[String] | |
and value writer1 of type => JsonWriter[String] | |
match expected type JsonWriter[String] | |
Json.toJson("A string") |
We can package type classes in the four ways:
- We can place it into the object.
- We can place it into the trait.
- We can place it into the companion object of the type class.
- We can place it into the companion object of the parameter type.
Recursive Implicit Resolution
When we create type classes and implicit, it will be that much capable as much as your compiler’s ability to combine them when searching for the instances.
So till now, we have created instances for the non-optional value but how can we create an instance for the Optional value? We can achieve it by creating the library for the implicit vals.
Is this cool?
WAIT …
We can not opt this solution because then we have to create the implicit vals for every type A which are in our application. One for A and second for Option[A]. we can abstract the code for handling Option[A] into a common constructor based on the instance for A :
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
implicit def optionWriter[A] | |
(implicit writer: JsonWriter[A]): JsonWriter[Option[A]] = | |
new JsonWriter[Option[A]] { | |
def write(option: Option[A]): Json = | |
option match { | |
case Some(aValue) => writer.write(aValue) | |
case None => JsNull | |
} | |
} |
Now we can pass here the Option value and test it:
So till now, we have already discussed the type classes and the implicit. Now as I mentioned at the beginning of the previous blog that “These are the base when we start learning the Scala Cats.”, I hope that we have some clarity about these topics and we can start Scala Cats here. We will discuss the basics of the Scala Cats in this blog.
Scala Cats
Cats are written using the modular structure which allows us to choose which type of the class, instance, and the interface methods.
Import Type Classes in Cats
We can import type classes in cats which are defining in the cats package. Here we are directly importing classes like:
Importing Default Instances
We can import instance in cats which are defining in the cats.instances package provides default instances for a wide variety of types. Example:
Importing Interface Syntax
We can use classes with more easier way by importing the interface syntax form cats.syntax.{$Class_Name}. Cats provides separate syntax imports for each type class.
Import all things
For importing all classes, interface and syntax, we can import like this:
- import cats.implicits._
- import cats.syntax.all._
- import cats.instances.all._
- import cats._
These are some basic feature of the Scala Cats. In this blog, we have talked about the implicit and Scala Cats. Now we have to look for the Semigroup and Monoids and you can find those blogs here: Semigroups & Monoids
Stay tunned for more blogs, we will come back with some other blogs on the Scala Cats 🙂
Till Then … Happy Coding 🙂
Reference:
Reblogged this on Anurag Srivastava.