# Kittens: automatic type class derivation for Cats on Scala 2 and Scala 3

> Kittens is a Typelevel library that derives Cats type class instances for arbitrary algebraic data types, using shapeless-based derivation on Scala 2 and the language's own derivation on Scala 3. It also ships utility functions for lifting, traversing and sequencing over HLists, Records and case classes, and the same artefact works on the JVM, Scala.js and Scala Native.

**typelevel/kittens** — Automatic type class derivation for Cats

- Repository: https://github.com/typelevel/kittens
- Stars: 545 · Forks: 66
- Language: Scala
- License: Apache-2.0
- Published: 2026-10-22 · Updated: 2026-10-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/typelevel-kittens

## Derivation for ADTs, with the type class list spelled out

Kittens is a Scala library which provides instances of type classes from the Cats library for arbitrary algebraic data types using Shapeless-based automatic type class derivation. It also provides utility functions related to Applicative such as lift, traverse and sequence to HList, Record and case classes.

So there are two halves to the library, and they are related. The type class instances are the headline feature, and the utility functions are the reason the type classes are worth deriving in the first place.

The Scala 2 instance list is long and specific, and it is worth reading to know what is covered.

- `Eq`, `PartialOrder`, `Order`, `Hash`
- `Show`, pretty `Show`
- `Empty`, `EmptyK` (from Alleycats)
- `Semigroup`, `CommutativeSemigroup`, `SemigroupK`
- `Monoid`, `CommutativeMonoid`, `MonoidK`
- `Functor`, `Contravariant`, `Invariant`
- `Pure` (from Alleycats), `Apply`, `Applicative`
- `Foldable`, `Reducible`
- `Traverse`, `NonEmptyTraverse`
- `ConsK` (from Alleycats)

Note which ones come from Alleycats rather than Cats: Empty, EmptyK, Pure and ConsK. So the effective dependency surface is Cats plus Alleycats, which is worth knowing if you are counting dependencies.

A derivation is a one line import of a companion object.

```scala
scala> import cats.implicits._, cats._, cats.derived._

scala> case class Cat[Food](food: Food, foods: List[Food])
defined class Cat

scala> val cat = Cat(1, List(2, 3))
cat: Cat[Int] = Cat(1,List(2, 3))
```

And then the instance is asked for by name.

```scala
scala> implicit val fc: Functor[Cat] = semiauto.functor
FC: cats.Functor[Cat] = cats.derived.MkFunctor2$$anon$4@1c60573f

scala> cat.map(_ + 1)
res0: Cat[Int] = Cat(2,List(3, 4))
```

So `semiauto.functor` is a value of type Functor[Cat], assigned to an implicit val, and from then on the standard Cats syntax works.

The primary language is Scala, the licence is Apache-2.0 with a LICENSE file and a CONTRIBUTORS file at the root, and the last push was on 2026-10-17. The release history is v3.5.0 from 2025-03-04, v3.4.0 from 2024-08-21 and v3.3.0 from 2024-03-08.

## Existing instances in scope are respected, and that is the point

The Show example in the README is the one that explains why semiauto is the recommended derivation mode, and it is worth following.

The setup is a nested structure, with an Address inside a ContactInfo inside a People.

```scala
scala> case class Address(street: String, city: String, state: String)
scala> case class ContactInfo(phoneNumber: String, address: Address)
scala> case class People(name: String, contactInfo: ContactInfo)

scala> val mike = People("Mike", ContactInfo("202-295-3928", Address("1 Main ST", "Chicago", "IL")))

scala> // existing Show instance for Address
scala> implicit val addressShow: Show[Address] =
         a => s"${a.street}, ${a.city}, ${a.state}"

scala> implicit val peopleShow: Show[People] = semiauto.show // auto derive Show for People
```

The comment calls out the existing instance, and the README then states what happened. The derivation generated instances for all referenced classes but still respected the existing instance in scope.

That is the behaviour that makes the library safe to use in a codebase with hand-written instances. If you wrote a custom Show for Address, the derived Show for People uses it for the nested field rather than generating a competing one.

The output is also different from the default toString, and the README notes that the derived Show also prints out field names, so it might be preferable to the default toString.

```scala
scala> mike.show
res0: String = People(name = Mike, contactInfo = ContactInfo(phoneNumber = 202-295-3928, address = 1 Main ST, Chicago, IL))
```

And there is a worked example of the composition. Show[List[A]] will use the native Show instance for List and derived instance for A.

So derivation is not a replacement for your hand-written instances. It fills the gaps around them, which is a different promise from the auto derivation mode that derives everything from scratch.

## Three derivation modes on Scala 2, with a real trade-off in each

The Scala 2 section says there are three options for type class derivation, cats.derived.auto, cats.derived.cached and cats.derived.semiauto, and that the recommended best practice is to use semiauto.

```scala
import cats.derived

implicit val showFoo: Show[Foo] = derived.semiauto.show
```

The three modes differ in where the instance lives and when it is computed.

Auto derivation is a wildcard import.

```scala
import derived.auto.show._
```

The downside is that it will derive an instance from scratch for every use site, increasing compilation time. That is a real cost in a large codebase, because derivation is not cheap and doing it per use site multiplies the work.

Cached derivation is the other wildcard import.

```scala
import derived.cached.show._
```

And the README tells you to use this one with caution, because it caches the derived instance globally. So it's only applicable if the instance is global in the application, and this could be problematic for libraries, which have no control over the uniqueness of an instance at use site.

That is an unusually direct statement of a hazard. In a library, your code is compiled into someone else's application, and if the application also has a cached instance for the same type, there is a conflict the library author cannot prevent.

Semiauto is the one line per type.

```scala
implicit val showFoo: Show[Foo] = derived.semiauto.show
```

The downside here is that we need to write one for every type that needs an instance.

So the trade is explicit compilation time against explicit lines. Auto is fast to write and slow to compile, cached is fast to compile and dangerous to publish, semiauto is one line per type and safe.

That framing is the reason semiauto is the recommendation. It puts the decision at the point where you know whether the instance should be global, and it makes the instance visible in the source rather than implicit.

## Scala 3 gets a different set of options, and a strict mode

The Scala 3 section is short in the visible README, but it lists the differences from Scala 2 and they are the ones that matter for a migration.

There are five options for type class derivation on Scala 3, and the recommended way is to import cats.derived.* and use derives clauses.

```scala
import cats.derived

implicit val showFoo: Show[Foo] = derived.semiauto.show
```

The three differences in contrast to Scala 2 are the important part.

Cached derivation is not supported, and also not necessary. That removes the hazard the Scala 2 section warns about, because there is no global cache to conflict over.

Type Class Derivation is supported, which is the Scala 3 language feature for deriving instances given a given instance in scope, rather than through a separate derivation mechanism.

A strict mode is available for semiauto and derives clauses.

Strict mode is worth understanding, because it is not in the Scala 2 story at all. In a non-strict derivation, the compiler will fall back to a generic derivation if it cannot find a specific instance for a field, which means a typo in a type name can silently produce a less precise instance rather than an error. Strict mode removes that fallback, so a missing instance becomes a compile error.

For a team moving from Scala 2 to Scala 3, that is the headline difference. The Scala 2 semiauto behaviour of respecting existing instances in scope has an equivalent in Scala 3, and the strict mode gives it teeth.

The cross platform support is unchanged. It is available for Scala 2.12 and 2.13, Scala.js 1.5 and Scala Native 0.4, which is the usual Typelevel range and means the same artefact works for a JVM service, a Scala.js front end and a Native build.

## lift, traverse and sequence are the utility half of the library

The utility functions are what turn derived instances into something you actually use, and they are documented with their own examples.

The lift example is the shortest.

```scala
scala> import cats._, implicits._, lift._
import cats._
import implicits._
import lift._

scala> def foo(x: Int, y: String, z: Float) = s"$x - $y - $z"

scala> val lifted = Applicative[Option].liftA(foo _)
```

So lift turns a three argument function into a function of three Options producing an Option, which is the usual applicative lifting but written against the derived instances.

The sequence examples are the more involved ones, and they need a compiler flag. To run these examples, you need partial unification enabled, and for Scala 2.12 you should add the following to your build.sbt.

```scala
scalacOptions += "-Ypartial-unification"
```

The example then sequences three functions into an HList.

```scala
scala> val f = sequence(f1, f2, f3)
f: String => shapeless.::[Int,shapeless.::[String,shapeless.::[Float,shapeless.HNil]]] = <function1>

scala> f("42.0")
res0: shapeless.::[Int,shapeless.::[String,shapeless.::[Float,shapeless.HNil]]] = 4 :: 0.24 :: 42.0 :: HNil
```

And the same thing generically over an ADT.

```scala
scala>  val myGen = sequenceGeneric[MyCase]
myGen: cats.sequence.sequenceGen[MyCase] = cats.sequence.SequenceOps$sequenceGen@63ae3243

scala> val f = myGen(a = f1, b = f2, c = f3)
f: String => MyCase = <function1>

scala> f("42.0")
res1: MyCase = MyCase(4,0.24,42.0)
```

Traverse works similarly except you need a shapeless.Poly.

The generic version is the interesting one. sequenceGeneric produces a sequence function for any case class, so you do not need to hand-write the Applicative for your type, which is the point of having derivation at all.

## Where Kittens is the wrong tool

The first wrong-tool case is a Scala 3 codebase that has adopted the language's own derivation. If you are on Scala 3, the README's recommended path is imports of cats.derived.* with derives clauses, and the built-in Type Class Derivation is supported. Kittens on Scala 3 is essentially a thin layer over what the compiler does, so the value of the library on Scala 3 is smaller, though the semiauto and strict modes still save you writing one val per type.

The second case is a library author. The cached derivation section says it directly: this could be problematic for libraries, which have no control over the uniqueness of an instance at use site. If you publish a library, you cannot use cached derivation, and if you rely on auto derivation you accept a compile time cost that your users pay.

The third case is a project that has no Cats. Everything here is about deriving instances of Cats type classes, and the utility functions are built around Applicative. If your algebra is not Cats, this library does nothing for you, and the shapeless dependency on Scala 2 is a heavy one to pull in for nothing.

The fourth case is a large data model with heavy instances. Derivation works by inspecting the structure of your type, and the cost grows with the depth and breadth of that structure. The README does not document how derivation scales for a deeply nested ADT, and the auto mode's compile time cost is called out as a downside without a figure. A codebase with hundreds of case classes and auto derivation is a compile time risk.

There is also a version compatibility constraint to note. It is available for Scala 2.12 and 2.13, Scala.js 1.5 and Scala Native 0.4, so a project on Scala 3.3 with an older Scala.js is outside the range, and on Scala 2.12 the sequence examples additionally need partial unification enabled.

The dependency story is worth knowing too. The Scala 2 derivation is Shapeless-based, and the Shapeless library has been in maintenance mode for years, so the Scala 2 path of Kittens sits on a foundation that is unlikely to gain features.

On licence, Apache-2.0 with a LICENSE file at the root, and binary artifacts are published to the Sonatype OSS Repository Hosting service and synced to Maven Central, so there is no question about where the artefact comes from. The project is part of the Typelevel family, which is a community of Scala libraries with a shared style and a shared release process, and the build.sbt, project/ and core/ directories at the root are a conventional sbt layout. The repository also carries a .scala-steward.conf file, which is how the project tracks upstream dependency bumps.

## Conclusion

Kittens suits a Scala team using Cats who has a lot of small case classes and does not want to hand-write an Eq or a Show for each one, since semiauto derivation gives you one line per type while respecting existing instances in scope. It does not suit a Scala 3 codebase that has already adopted the language's own derives clauses, and it does not suit a library author who needs guaranteed instance uniqueness, which the cached derivation warns about explicitly. Before adopting, check the type class support matrix in the README for the instances you actually need, since some of them come from Alleycats rather than Cats, and note that on Scala 2 you will need -Ypartial-unification for the sequence examples.

## FAQ

### What is Typelevel Kittens?

Kittens is a Scala library that provides instances of Cats type classes for arbitrary algebraic data types using Shapeless-based automatic derivation on Scala 2. It also provides utility functions related to Applicative such as lift, traverse and sequence to HList, Record and case classes.

### How do I add Kittens to an sbt build?

Add libraryDependencies += "org.typelevel" %% "kittens" % "latestVersion" to your build.sbt file, with the version indicated in the badge. Binary artefacts are published to Sonatype OSS Repository Hosting and synced to Maven Central.

### Which derivation mode should I use in Kittens on Scala 2?

The README recommends semiauto, written as implicit val showFoo: Show[Foo] = derived.semiauto.show, because it respects existing instances in scope and caches the result manually. Auto derivation recompiles an instance per use site and slows compilation, and cached derivation caches globally, which the README warns is problematic for libraries.

### What changes between Kittens on Scala 2 and Scala 3?

On Scala 3 the README recommends importing cats.derived.* and using derives clauses, cached derivation is not supported and is not necessary, the Scala 3 Type Class Derivation feature is supported, and a strict mode is available for semiauto and derives clauses.

### Which type class instances can Kittens derive?

Eq, PartialOrder, Order, Hash, Show, pretty Show, Empty, EmptyK, Semigroup, CommutativeSemigroup, SemigroupK, Monoid, CommutativeMonoid, MonoidK, Functor, Contravariant, Invariant, Pure, Apply, Applicative, Foldable, Reducible, Traverse, NonEmptyTraverse and ConsK. Empty, EmptyK, Pure and ConsK come from Alleycats rather than Cats.

### What license is Kittens released under?

Kittens is an Open Source project under the Apache License v2, with the LICENSE file at the root of the repository. It is part of the Typelevel family of projects, is available for Scala 2.12 and 2.13, Scala.js 1.5 and Scala Native 0.4, and the current release is v3.5.0.

## Sources

- [Issues](https://github.com/typelevel/kittens/issues)
- [License: Apache-2.0](https://github.com/typelevel/kittens/blob/master/LICENSE)
- [README](https://github.com/typelevel/kittens/blob/master/README.md)
- [Releases](https://github.com/typelevel/kittens/releases)
- [typelevel/kittens on GitHub](https://github.com/typelevel/kittens)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/typelevel-kittens
