Frequently Asked Questions
Questions
 What imports do I need?
 I am new to pure functional programming, what quick wins can I get from Cats?
 What is the difference between Cats and Scalaz?
 Where is rightbiased
Either
?  Why is the compiler having trouble with types with more than one type parameter?
 Why can’t the compiler find implicit instances for Future?
 Why is some example code not compiling for me?
 How can I turn my List of
<something>
into a<something>
of a list?  Where is
ListT
?  [Where are
Applicative
s for monad transformers?(#applicativemonadtransformers)  Where is
IO
/Task
?  What does
@typeclass
mean?  What do types like
?
andλ
mean?  What does
macro Ops
do? What iscats.macros.Ops
?  What is
tailRecM
?  What does this symbol mean?
 How can I test instances against their type classes’ laws?
 How can I help?
 Is there a sbt plugin that facilitate projects based on the Cats ecosystem libraries?
 Why aren’t monad transformers like
OptionT
andEitherT
covariant likeOption
andEither
?  How to try cats in a REPL?
What imports do I need?
The easiest approach to cats imports is to import everything that’s commonly needed:
import cats._
import cats.data._
import cats.implicits._
This should be all that you need, but if you’d like to learn more about the details of imports than you can check out the import guide.
I am new to pure functional programming, what quick wins can I get from Cats?
Please refer to the jump start guide.
What is the difference between Cats and Scalaz?
Cats and Scalaz have the same goal: to facilitate pure functional programming in Scala applications. However the underlying core strategy is different; Scalaz took the approach of trying to provide a single batteriesincluded standard library for FP that powers the Scala applications. Cats, on the other hand, aims to help build an ecosystem of pure FP libraries by providing a solid and stable foundation; these libraries can have their own styles and personalities, competing with each other, while at the same time playing nice. It is through this ecosystem of FP libraries (cats included) that Scala applications can be powered with “FP awesomeness” and beyond by picking whatever best fit their needs.
Based on this core strategy, Cats takes a modular approach and focuses on providing core, binary compatible, approachable and efficient abstractions. It provides a welcoming and supportive environment for the user community governed by the typelevel code of conduct. It also takes great effort in supplying a comprehensive and beginnerfriendly documentation.
Where is rightbiased Either?
Up through Cats 0.7.x we had cats.data.Xor
, which was effectively scala.util.Either
, but rightbiased by default and with
a bunch of useful combinators around it. In Scala 2.12.x Either
became rightbiased so we revisited the use of Xor
and
decided that in the interest of interoperability, we would remove Xor
in the Cats 0.8.0 release and
fill in the gaps in the scala.util.Either
API via
syntax enrichment.
This syntax and the type class instances for Either
can be imported using cats.implicits._
, which will also bring in syntactic enrichment and instances for other standard library types, or you can import them individually with cats.syntax.either._
and cats.instances.either._
.
There are a few minor mismatches between Xor
and Either
. For example, in some cases you may need to specify a type parameter for an enrichment method on Either
(such as leftMap
) even though it was properly inferred for Xor
. See the Either
section of this guide for more information about these issues.
Similarly, cats.data.XorT
has been replaced with cats.data.EitherT
, although since this is a type defined in Cats, you don’t need to import syntax or instances for it (although you may need imports for the underlying monad).
Why is the compiler having trouble with types with more than one type parameter?
When you encounter a situation where the same code works fine with a type with one type parameter, e.g. List[A], but doesn’t work with types with more than one, e.g. Either[A, B], you probably hit SI2712. Without going into the details, it’s highly recommended to enable a partial SI2712 fix in your project. The easiest way to achieve that is through this sbt plugin. Cats used to provide mitigation to this issue semitransparently, but given the fact that the fix is now mainstream, we decided to drop that mitigation machinery in favor of reducing the complexity. See this issue for details.
Why is some example code not compiling for me?
A portion of example code requires either the Kindprojector compiler plugin or partial unification turned on in scalac. The easiest way to turn partial unification on is through this sbt plugin.
Why can’t the compiler find implicit instances for Future?
If you have already followed the imports advice but are still getting error messages like could not find implicit value for parameter e: cats.Monad[scala.concurrent.Future]
or value + is not a member of scala.concurrent.Future[Int]
, then make sure that you have an implicit scala.concurrent.ExecutionContext
in scope. The easiest way to do this is to import scala.concurrent.ExecutionContext.Implicits.global
, but note that you may want to use a different execution context for your production application.
How can I turn my List of <something>
into a <something>
of a list?
It’s really common to have a List
of values with types like Option
, Either
, or Validated
that you would like to turn “inside out” into an Option
(or Either
or Validated
) of a List
. The sequence
and traverse
methods are really handy for this. You can read more about them in the Traverse documentation.
Where is ListT?
There are monad transformers for various types, such as OptionT, so people often wonder why there isn’t a ListT
. For example, in the following example, people might reach for ListT
to simplify making nested map
and exists
calls:
val l: Option[List[Int]] = Some(List(1, 2, 3, 4, 5))
def isEven(i: Int): Boolean = i % 2 == 0
l.map(_.map(_ + 1))
// res0: Option[List[Int]] = Some(List(2, 3, 4, 5, 6))
l.exists(_.exists(isEven))
// res1: Boolean = true
A naive implementation of ListT
suffers from associativity issues; see this gist for an example. It’s possible to create a ListT
that doesn’t have these issues, but it tends to be pretty inefficient. For many usecases, Nested can be used to achieve the desired results.
Here is how we could achieve the effect of the previous example using Nested
:
import cats.data.Nested
import cats.implicits._
val nl = Nested(l)
// nl: cats.data.Nested[Option,List,Int] = Nested(Some(List(1, 2, 3, 4, 5)))
nl.map(_ + 1)
// res2: cats.data.Nested[Option,List,Int] = Nested(Some(List(2, 3, 4, 5, 6)))
nl.exists(isEven)
// res3: Boolean = true
We can even perform more complicated operations, such as a traverse
of the nested structure:
import cats.data.ValidatedNel
type ErrorsOr[A] = ValidatedNel[String, A]
def even(i: Int): ErrorsOr[Int] = if (i % 2 == 0) i.validNel else s"$i is odd".invalidNel
nl.traverse(even)
// res4: ErrorsOr[cats.data.Nested[Option,List,Int]] = Invalid(NonEmptyList(1 is odd, 3 is odd, 5 is odd))
Where are Applicative
s for monad transformers?
An Applicative
instance for OptionT[F, ?]
/EitherT[F, E, ?]
, built without a corresponding Monad
instance for F
, would be unlawful, so it’s not included. See https://typelevel.org/cats/guidelines.html#applicativemonadtransformers for a more detailed explanation.
As an alternative, using .toNested
on the monad transformer is recommended, although its ap
will still be inconsistent with the Monad instance’s.`.
Where is IO/Task?
In purely functional programming, a monadic IO
or Task
type is often used to handle side effects such as file/network IO. In some languages and frameworks, such a type also serves as the primary abstraction through which parallelism is achieved. Nearly every realworld purely functional application or service is going to require such a data type, and this gives rise to an obvious question: why doesn’t cats include such a type?
The answer is that cats does include an IO
, it just isn’t included in the core library. The decision was made to split IO
away from catscore and (indeed the whole cats release cycle!) in order to make it easier to ensure modular versioning and compatibility across the ecosystem. The catseffect project defines a type, cats.effect.IO
, which is intended to be a very minimal, very performant data type for managing synchronous and asynchronous sideeffects, integrated into the cats ecosystem.
However, we acknowledge that this type may not meet everyone’s needs. The catseffect project characterizes the space of sideeffectcapturing data types with a set of typeclasses (deriving from cats.Monad
), and so all such data types are, broadlyspeaking, mutually compatible and interchangeable in many generic contexts. For example, Monix provides support for IO, concurrency, and streaming and integrates with the catseffect type classes.
It may be worth keeping in mind that IO
and Task
are pretty blunt instruments (they are essentially the Any
of side effect management), and you may want to narrow the scope of your effects throughout most of your application. The free monad documentation describes a way to abstractly define controlled effects and interpret them into a type such as IO
or Task
as late as possible. As more of your code becomes pure through these controlled effects the less it matters which type you end up choosing to represent your side effects.
What does @typeclass
mean?
Cats defines and implements numerous type classes. Unfortunately, encoding these type classes in Scala can incur a large amount of boilerplate. To address this, Simulacrum introduces @typeclass
, a macro annotation which generates a lot of this boilerplate. This elevates type classes to a first class construct and increases the legibility and maintainability of the code. Use of simulacrum also ensures consistency in how the type classes are encoded across a project. Cats uses simulacrum wherever possible to encode type classes, and you can read more about it at the project page.
Note that the one area where simulacrum is intentionally not used is in the catskernel
module. The catskernel
module is intended to be a shared dependency for a number of projects, and as such, it is important that it is both lightweight and very stable from a binary compatibility perspective. At some point there may be a transition from simulacrum to typeclassic, and the binary compatibility of moving between simulacrum and typeclassic is unclear at this point. Avoiding the dependency on simulacrum in catskernel
, provides insulation against any potential binary compatibility problems in such a transition.
What do types like ?
and λ
mean?
Cats defines a wealth of type classes and type class instances. For a number of the type class and instance combinations, there is a mismatch between the type parameter requirements of the type class and the type parameter requirements of the data type for which the instance is being defined. For example, the Either data type is a type constructor with two type parameters. We would like to be able to define a Monad for Either
, but the Monad
type class operates on type constructors having only one type parameter.
Enter type lambdas! Type lambdas provide a mechanism to allow one or more of the type parameters for a particular type constructor to be fixed. In the case of Either
then, when defining a Monad
for Either
, we want to fix one of the type parameters at the point where a Monad
instance is summoned, so that the type parameters line up. As Either
is right biased, a type lambda can be used to fix the left type parameter and allow the right type parameter to continue to vary when Either
is treated as a Monad
. The right biased nature of Either
is discussed further in the Either
documentation.
Enter kindprojector! kindprojector is a compiler plugin which provides a convenient syntax for dealing with type lambdas. The symbols ?
and λ
are treated specially by kindprojector, and expanded into the more verbose definitions that would be required were it not to be used. You can read more about kindprojector at the project page.
What does macro Ops
do? What is cats.macros.Ops
?
macro Ops
invokes the Machinist Ops macro, and is used in cats in a number of places to enrich types with operations with the minimal possible cost when those operations are called in code. Machinist supports an extension mechanism where users of the macro can provide a mapping between symbolic operator names and method names. The cats.macros.Ops
class uses this extension mechanism to supply the set of mappings that the cats project is interested in.
More about the history of machinist and how it works can be discovered at the project page, or this article on the typelevel blog.
What is tailRecM
?
The FlatMap
type class has a tailRecM
method with the following signature:
def tailRecM[A, B](a: A)(f: A => F[Either[A, B]]): F[B]
When you are defining a FlatMap
instance, its tailRecM
implementation must have two properties in order for the instance to be considered lawful. The first property is that tailRecM
must return the same result that you would get if you recursively called flatMap
until you got a Right
value (assuming you had unlimited stack space—we’ll get to that in a moment). In other words, it must give the same result as this implementation:
trait Monad[F[_]] {
def pure[A](x: A): F[A] = ???
def flatMap[A, B](fa: F[A])(f: A => F[B]): F[B] = ???
def tailRecM[A, B](a: A)(f: A => F[Either[A, B]]): F[B] =
flatMap(f(a)) {
case Right(b) => pure(b)
case Left(nextA) => tailRecM(nextA)(f)
}
}
The reason we can’t simply use this implementation for all type constructors (and the reason that tailRecM
is useful at all) is that for many monadic types, recursively flatMap
ing in this way will quickly exhaust the stack.
Option
is one example of a monadic type whose flatMap
consumes stack in such a way that nesting flatMap
calls deeply enough (usually around a couple thousand levels) will result in a stack overflow. We can provide a stacksafe tailRecM
implementation for Option
, though:
import cats.FlatMap
import scala.annotation.tailrec
implicit val optionFlatMap: FlatMap[Option] = new FlatMap[Option] {
def map[A, B](fa: Option[A])(f: A => B): Option[B] = fa.map(f)
def flatMap[A, B](fa: Option[A])(f: A => Option[B]): Option[B] = fa.flatMap(f)
@tailrec
def tailRecM[A, B](a: A)(f: A => Option[Either[A, B]]): Option[B] = f(a) match {
case None => None
case Some(Left(a1)) => tailRecM(a1)(f)
case Some(Right(b)) => Some(b)
}
}
Now we don’t have to worry about overflowing the stack, no matter how many times we have to call tailRecM
before we get a Right
.
This is useful because any operation that you would write using recursive flatMap
s can be rewritten to use tailRecM
, and if the FlatMap
instance for your type constructor is lawful, you don’t have to worry about stack safety.
The downside is that how you write a lawful tailRecM
for your type constructor may not always be obvious. For some type constructors, such as Future
, recursively flatMap
ing is already safe, and the first simple implementation above will be lawful. For types like Option
and Try
, you’ll need to arrange the recursion in such a way that the tailRecM
calls are tail calls (which you can confirm with Scala’s tailrec
annotation). Collection types require yet another approach (see for example the implementation for List
).
If you’re having trouble figuring out how to implement tailRecM
lawfully, you can try to find an instance in Cats itself for a type that is semantically similar to yours (all of the FlatMap
instances provided by Cats have lawful, stacksafe tailRecM
implementations).
In some cases you may decide that providing a lawful tailRecM
may be impractical or even impossible (if so we’d like to hear about it). For these cases we provide a way of testing all of the monad laws except for the stack safety of tailRecM
: just replace MonadTests[F].monad[A, B, C]
in your tests with MonadTests[F].stackUnsafeMonad[A, B, C]
.
What does this symbol mean?
Below is a list of symbols used in cats.
The ~>
, ⊥
, ⊤
, :<:
and :≺:
symbols can be imported with import cats._
.
All other symbols can be imported with import cats.implicits._
Symbol  Name  Nickname  Type Class  Signature 

fa *> fb 
product right  Apply[F[_]] 
productR(fa: F[A])(fb: F[B]): F[B] 

fa <* fb 
product left  Apply[F[_]] 
productL(fa: F[A])(fb: F[B]): F[A] 

x === y 
equals  Eq[A] 
eqv(x: A, y: A): Boolean 

x =!= y 
not equals  Eq[A] 
neqv(x: A, y: A): Boolean 

fa >>= f 
flatMap  FlatMap[F[_]] 
flatMap(fa: F[A])(f: A => F[B]): F[B] 

fa >> fb 
followed by  FlatMap[F[_]] 
>>(fb: => F[B]): F[B] 

x  y 
remove  Group[A] 
remove(x: A, y: A): A 

x > y 
greater than  PartialOrder[A] 
gt(x: A, y: A): Boolean 

x >= y 
greater than or equal  PartialOrder[A] 
gteq(x: A, y: A): Boolean 

x < y 
less than  PartialOrder[A] 
lt(x: A, y: A): Boolean 

x <= y 
less than or equal  PartialOrder[A] 
lteq(x: A, y: A): Boolean 

x + y 
Semigroup combine  Semigroup[A] 
combine(x: A, y: A): A 

x <+> y 
SemigroupK combine  SemigroupK[F[_]] 
combineK(x: F[A], y: F[A]): F[A] 

f <<< g 
Arrow compose  Compose[F[_, _]] 
compose(f: F[B, C], g: F[A, B]): F[A, C] 

f >>> g 
Arrow andThen  Compose[F[_, _]] 
andThen(f: F[B, C], g: F[A, B]): F[A, C] 

f &&& g 
Arrow merge  Arrow[F[_, _]] 
merge[A, B, C](f: F[A, B], g: F[A, C]): F[A, (B, C)] 

f < g 
Arrow combine and bypass  Arrow[F[_, _]] 
combineAndByPass[A, B, C](f: F[A, B], g: F[B, C]): F[A, (B, C)] 

F ~> G 
natural transformation  FunctionK[F[_], G[_]] 
FunctionK alias 

F :<: G 
injectK  InjectK[F[_], G[_]] 
InjectK alias 

F :≺: G 
injectK  InjectK[F[_], G[_]] 
InjectK alias 

fa &> fb 
parallel product right  Parallel[M[_], F[_]] 
parProductR[A, B](ma: M[A])(mb: M[B]): M[B] 

fa <& fb 
parallel product left  Parallel[M[_], F[_]] 
parProductL[A, B](ma: M[A])(mb: M[B]): M[A] 

⊥ 
bottom  N/A  Nothing 

⊤ 
top  N/A  Any 

fa << fb (Deprecated) 
product left  FlatMap[F[_]] 
productL(fa: F[A])(fb: F[B]): F[A] 
How can I test instances against their type classes’ laws?
You can find more information here.
How can I help?
The cats community welcomes and encourages contributions, even if you are completely new to cats and functional programming. Here are a few ways to help out:
 Find an undocumented method and write a ScalaDoc entry for it. See Arrow.scala for some examples of ScalaDoc entries that use sbtdoctest.
 Look at the code coverage report, find some untested code, and write a test for it. Even simple helper methods and syntax enrichment should be tested.
 Find an open issue, leave a comment on it to let people know you are working on it, and submit a pull request. If you are new to cats, you may want to look for items with the lowhangingfruit label.
See the contributing guide for more information.
Is there a sbt plugin that facilitate projects based on the Cats ecosystem libraries?
Of course. sbtcatalysts is created particularly for this purpose. It also provides a g8 template so that you can run sbt new typelevel/sbtcatalysts.g8
to quickly set up a project using Cats ecosystem libraries through this plugin. For more details, go to sbtcatalysts.
How to try Cats in a REPL?
The easiest way is probably using AmmoniteREPL. Install it following the instructions there. Then in the amm console you can type in
interp.configureCompiler(_.settings.YpartialUnification.value = true)
import $ivy.`org.typelevel::catscore:1.0.1`, cats.implicits._
Or if you want, you can add these lines to ~/.ammonite/predef.sc
so that they are enabled every ammonite session.
Why aren’t monad transformers like OptionT
and EitherT
covariant like Option
and Either
?
Please see Variance of Monad Transformers on the Typelevel blog.