DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Last call! Secure your stack and shape the future! Help dev teams across the globe navigate their software supply chain security challenges.

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Releasing software shouldn't be stressful or risky. Learn how to leverage progressive delivery techniques to ensure safer deployments.

Avoid machine learning mistakes and boost model performance! Discover key ML patterns, anti-patterns, data strategies, and more.

Related

  • Mastering Advanced Aggregations in Spark SQL
  • Thermometer Continuation in Scala
  • Deploying a Scala Play Application to Heroku: A Step-by-Step Guide
  • Upgrading Spark Pipelines Code: A Comprehensive Guide

Trending

  • Mastering Advanced Aggregations in Spark SQL
  • Enhancing Security With ZTNA in Hybrid and Multi-Cloud Deployments
  • Scaling DevOps With NGINX Caching: Reducing Latency and Backend Load
  • Medallion Architecture: Efficient Batch and Stream Processing Data Pipelines With Azure Databricks and Delta Lake
  1. DZone
  2. Coding
  3. Languages
  4. Getting Started with Scala Cats

Getting Started with Scala Cats

In this article, we'll get started with Cats, which is one of the functional libraries of Scala.

By 
Mansi Babbar user avatar
Mansi Babbar
·
Jan. 31, 21 · Tutorial
Likes (4)
Comment
Save
Tweet
Share
5.9K Views

Join the DZone community and get the full member experience.

Join For Free

This blog was first published on Knoldus Blogs


Introduction

This article is about Scala Cats. It is a library which provides abstraction for functional programming in the Scala programming language. The name is a playful shortening of the word category.

Cats is a lightweight, modular, and extensible library for functional programming.

Cats contains a wide variety of functional programming tools and allows developers to pick the required ones. The majority of these tools are delivered in the form of type classes that we can apply to existing Scala types.

What are Type Classes?

Type classes are a programming pattern originating in Haskell. They allow us to extend existing libraries with new functionality, without using traditional inheritance, and without altering the original library source code.

There are three important components to the type class pattern: the type class itself, instances for particular types, and the methods that use type classes.

What is a Type Class?

A type class is an interface or API that represents some functionality we want to implement. In Scala a type class is represented by a trait with at least one type parameter.

For example, we can represent generic “serialize to JSON” behavior as follows:

Scala
 




xxxxxxxxxx
1
11


 
1
// Define a very simple JSON AST
2
sealed trait Json
3
final case class JsObject(get: Map[String, Json]) extends Json
4
final case class JsString(get: String) extends Json
5
final case class JsNumber(get: Double) extends Json
6
final case object JsNull extends Json
7
 
          
8
// The "serialize to JSON" behaviour is encoded in this trait
9
trait JsonWriter[A] {
10
  def write(value: A): Json
11
}


What are Type Class Instances?

The instances of a type class provide implementations of the type class for specific types we care about, which can include types from the Scala standard library and types from our domain model.

In Scala we define instances by creating concrete implementations of the type class and tagging them with the implicit keyword:

Scala
 




xxxxxxxxxx
1
14


 
1
final case class Person(name: String, email: String)
2
 
          
3
object JsonWriterInstances {
4
  implicit val stringWriter: JsonWriter[String] = new JsonWriter[String] {
5
    def write(value: String): Json = JsString(value)
6
  }
7
  implicit val personWriter: JsonWriter[Person] = new JsonWriter[Person] {
8
    def write(value: Person): Json =
9
      JsObject(Map(
10
        "name" -> JsString(value.name),
11
        "email" -> JsString(value.email)
12
      ))
13
  }
14
}


How to use a Type Class?

A type class use is any functionality that requires a type class instance to work. In Scala this means any method that accepts instances of the type class as implicit parameters.

Cats provides utilities that make type classes easier to use, and you will sometimes seem these patterns in other libraries.

There are two ways it does this: Interface Objects and Interface Syntax.

What are Interface Objects?

The simplest way of creating an interface that uses a type class is to place methods in a singleton object:

Scala
 




xxxxxxxxxx
1


 
1
object Json {
2
  def toJson[A](value: A)(implicit w: JsonWriter[A]): Json = w.write(value)
3
}


To use this object, we import any type class instances we care about and call the relevant method:

Scala
 




xxxxxxxxxx
1


 
1
import JsonWriterInstances._
2
Json.toJson(Person("Dave", "dave@example.com"))


The compiler spots that we’ve called the toJson method without providing the implicit parameters. It tries to fix this by searching for type class instances of the relevant types and inserting them at the call site:

Scala
 




xxxxxxxxxx
1


 
1
Json.toJson(Person("Dave", "dave@example.com"))(personWriter)


What is Interface Syntax?

We can alternatively use extension methods to extend existing types with interface methods. Cats refers to this as “syntax” for the type class:

Scala
 




xxxxxxxxxx
1


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


We use interface syntax by importing it alongside the instances for the types we need:

Scala
 




xxxxxxxxxx
1


 
1
import JsonWriterInstances._
2
import JsonSyntax._
3
Person("Dave", "dave@example.com").toJson


Again, the compiler searches for candidates for the implicit parameters and fills them in for us:

Scala
 




xxxxxxxxxx
1


 
1
Person("Dave", "dave@example.com").toJson(personWriter)


What are Implicits?

Working with type classes in Scala means working with implicit values and implicit parameters. There are a few rules we need to know to do this effectively.

Any definitions marked implicit in Scala must be placed inside an object or trait rather than at the top level. 

In the example above we packaged our type class instances in an object called JsonWriterInstances. We could equally have placed them in a companion object to JsonWriter. Placing instances in a companion object to the type class has special significance in Scala because it plays into something called implicit scope.

What is Implicit Scope?

As we saw above, the compiler searches for candidate type class instances by type.

For example, in the following expression it will look for an instance of type JsonWriter[String]:

Scala
 




xxxxxxxxxx
1


 
1
Json.toJson("A string!")


The places where the compiler searches for candidate instances is known as the implicit scope. The implicit scope applies at the call site that is the point where we call a method with an implicit parameter.

Summary

In this article, we had a first look at type classes. 

We saw the components that make up a type class:

  • A trait, which is the type class.
  • Type class instances, which are implicit values.
  • Type class usage, which uses implicit parameters.

Learning Template

You can download the learning template Scala Cats - Basics demonstrating the code implementations provided in this article.

References

The best two Scala Cats resources I know are here:

  • The Cats library is available at github.com/typelevel/cats
  • The book, Advanced Scala with Cats, is available at underscore.io/books/advanced-scala/
Scala (programming language) Type class

Opinions expressed by DZone contributors are their own.

Related

  • Mastering Advanced Aggregations in Spark SQL
  • Thermometer Continuation in Scala
  • Deploying a Scala Play Application to Heroku: A Step-by-Step Guide
  • Upgrading Spark Pipelines Code: A Comprehensive Guide

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!