The easiest approach to Сats imports is to import everything that’s commonly needed:
import cats._ import cats.data._ import cats.implicits._
cats._ import brings in quite a few type classes (similar to interfaces) such as Monad, Semigroup, and Foldable. Instead of the entire
cats package, you can import only the types that you need, for example:
import cats.Monad import cats.Semigroup import cats.Foldable
import cats.data.Validated import cats.data.State
cats.implicits._ import does a couple of things. Firstly, it brings in implicit type class instances for standard library types - so after this import you will have
Semigroup[Int] instances in implicit scope. Secondly, it adds syntax enrichment onto certain types to provide some handy methods such as right-biased
// Сats adds right-biased combinators to the standard library's Either val e: Either[String, Int] = Right(3) // e: Either[String, Int] = Right(3) e.map(_ + 1) // res0: Either[String, Int] = Right(4) // cats adds an orEmpty method to the standard library's Option val o: Option[String] = None // o: Option[String] = None o.orEmpty // res1: String = ""
If you’d like to import à la carte, you can do so, by importing from
cats.instances for the type class instances and
cats.syntax for syntax enrichment.
For example, if you’d like to import the
Monoid instance for
String and the corresponding syntax:
import cats.instances.string._ "Hello, " |+| "World!" // res2: String = "Hello, World!"
The first import pulls the
Semigroup instance for String into the scope, while the second import adds the
You can also import all syntax or all instances by importing
For data types included in cats (i.e. data structure from the
cats.data package), all type class instances are bundled with their implementation and therefore do not need to be imported separately.
For example, if we wanted to import
NonEmptyList from the
cats.data package and use its
SemigroupK instance, we would not need to specifically import the instance:
import cats.data.NonEmptyList NonEmptyList.of(1,2) <+> NonEmptyList.of(3,4) // res3: NonEmptyList[Int] = NonEmptyList(1, List(2, 3, 4))
Note: Beware that if you import a type class instance or its syntax twice, you will receive conflicting implicits with a less than helpful error message.
This usually happens when importing different type classes in the same hierarchy or when importing syntax enrichment for all type classes using
cats.implicits._ together with a more specific import like
Below is an example of this phenomenon:
import cats.instances.all._ val x = -2 |+| 1 // now we also need access to isEmpty from Monoid import cats.syntax.monoid._ (x |+| 1).isEmpty //error: value |+| is not a member of Int
Compilation fails on the second invocation of
|+| because we now have conflicting implicits from