ScalaFP: Let’s Start with Type Class

Table of contents
Reading Time: 2 minutes

Before we start talking about the Functional Programming with the Scala Cats, we should refresh our memory about the Type Class and Implicit. These are the base when we start learning the Scala Cats.

Let’s start the discussion with the Type Class.

Type Class

A type class is an interface or API that represents some functionality, which we want to implement. Type class is programming pattern in Haskell which allows us to extend existing libraries with new functionality. In Cats, a type class is represented by a trait with at least one type parameter.(If you don’t know about the trait or want to refresh look here: Back2Basics: The Story of Trait – Part 1)

Now we will see, how can we implement Type Class with traits:



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


sealed trait Json
final case class JsObject(get: Map[String, Json]) extends Json
final case class JsString(get: String) extends Json
final case class JsNumber(get: Double) extends Json
case object JsNull extends Json
trait JsonWriter[A] {
def write(value: A): Json
}

Here as we can see that JsonWriter is a Type class with the Json which provides the support for the rest operations.

Now we will discuss the Type Class Instances because it provides the implementation for the types.  Now in Scala, we create the instance with the help of concrete implementation and implicit. Example:



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


final case class Person(name: String, email: String)
object JsonWriterInstances {
implicit val stringWriter: JsonWriter[String] =
new JsonWriter[String] {
def write(value: String): Json = JsString(value)
}
implicit val personWriter: JsonWriter[Person] =
new JsonWriter[Person] {
def write(value: Person): Json =
JsObject(Map(
"name" > JsString(value.name),
"email" > JsString(value.email)
))
}
}

Now we will create a Type Class Interface, which will expose the functionality to the users. Interface use the generic method that will take the instance of the type class as an implicit parameter. We can access interface in two way:

  1. Interface Object
  2. Interface Syntax

Interface Object: Now we can create an interface. It will place a method into a singleton object:



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


object Json {
def toJson[A](value: A)(implicit w: JsonWriter[A]): Json = w.write(value)
}
view raw

Json.scala

hosted with ❤ by GitHub

Now we can call it like this:



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


import JsonWriterInstances._
Json.toJson(Person("Dave", "dave@example.com"))
//res1: Json = JsObject(Map(name -> JsString(Dave), email -> JsString(dave@example.com)))
view raw

Example.scala

hosted with ❤ by GitHub

Here we can see that we haven’t provided the implicit parameter but we are calling the toJson method. Now compiler will search for the type class instance and provide it to the call like:

Interface Syntax: We can use extension methods also for extending the existing type with the interface.



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


object JsonSyntax {
implicit class JsonWriterOps[A](value: A) {
def toJson(implicit w: JsonWriter[A]): Json =
w.write(value)
}
}

Now we can use it, like this:



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


import JsonWriterInstances._
import JsonSyntax._
Person("Dave", "dave@example.com").toJson
// res6: Json = JsObject(Map(name -> JsString(Dave), email -> JsString(dave@example.com)))

Again we can see that we haven’t provided the implicit parameter but we are calling the toJson method. Now compiler will search for the type class instance and provide it to the call like:

So we have discussed till now for the Type Class. In our next blog, we will talk about the Implicit and Scala Cat Structure.

Reference:

Scala with Cats


knoldus-advt-sticker


 

Written by 

Anurag is the Sr. Software Consultant @ Knoldus Software LLP. In his 3 years of experience, he has become the developer with proven experience in architecting and developing web applications.

5 thoughts on “ScalaFP: Let’s Start with Type Class2 min read

Comments are closed.