# Kittens: automatic type class derivation for Cats

**Kittens** is a Scala library which provides instances of type classes from the Cats library for arbitrary algebraic data types (ADTs) 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.

Kittens is part of the Typelevel family of projects. It is an Open Source project under the Apache License v2, hosted on GitHub. Binary artifacts will be published to the Sonatype OSS Repository Hosting service and synced to Maven Central.

It is available for Scala 2.12, 2.13 and Scala.js.

To get started with sbt, simply add the following to your `build.sbt`

file:

`libraryDependencies += "org.typelevel" %% "kittens" % "2.2.1"`

Instance derivations are available for the following type classes:

`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)

See the Type class support matrix for more details.

### Derivation examples

```
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))
```

`Functor`

Derive ```
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))
```

`Show`

Derive Note that the derived `Show`

also prints out field names, so it might be preferable to the default `toString`

:

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

Note that in this example, the derivation generated instances for all referenced classes but still respected the existing instance in scope. For different ways to derive instances please see the three modes of derivation below.

### Sequence examples

Note that to run these examples you need partial unification enabled. For **Scala 2.12** you should add the following to your `build.sbt`

:

`scalacOptions += "-Ypartial-unification"`

```
scala> import cats.implicits._, cats.sequence._
import cats.implicits._
import cats.sequence._
scala> val f1 = (_: String).length
f1: String => Int = <function1>
scala> val f2 = (_: String).reverse
f2: String => String = <function1>
scala> val f3 = (_: String).toFloat
f3: String => Double = <function1>
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
//or generic over ADTs
scala> case class MyCase(a: Int, b: String, c: Float)
defined class MyCase
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`

.

### Lift examples

```
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 _)
lifted: (Option[Int], Option[String], Option[Float]) => Option[String] = <function3>
scala> lifted(Some(1), Some("a"), Some(3.2f))
res0: Option[String] = Some(1 - a - 3.2)
```

### Three modes of derivation

Kittens provides three objects for derivation `cats.derived.auto`

, `cats.derived.cached`

and `cats.derived.semi`

The recommended best practice is going to be a semi auto one:

```
import cats.derived
implicit val showFoo: Show[Foo] = {
import derived.auto.show._
derived.semiauto.show
}
```

This will respect all existing instances even if the field is a type constructor. For example `Show[List[A]]`

will use the native `Show`

instance for `List`

and derived instance for `A`

. And it manually caches the result to the `val showFoo`

. Downside user will need to write one for every type they directly need a `Show`

instance.

There are 3 alternatives:

- full auto:

`import derived.auto.show._`

The downside is that it will re-derive for every use site, which multiples the compilation time cost.

- full auto cached

`import derived.cached.show._`

Use this one with caution. It caches the derived instance globally. So it's only applicable if the instance is global in the application. This could be problematic for libraries, which has no control over the uniqueness of an instance on use site. It relies on `shapeless.Cached`

which is buggy.

- manual semi

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

It has the same downside as the recommenced semi-auto practice but also suffers from the type constructor field issue. I.e. if a field type is a type constructor whose native instance relies on the instance of the parameter type, this approach will by default derive an instance for the type constructor one. To overcome this user have to first derive the instance for type parameter. e.g. given:

```
case class Foo(bars: List[Bar])
case class Bar(a: String)
```

Since the `bars`

field of `Foo`

is a `List`

of `Bar`

which breaks the chains of auto derivation, you will need to derive `Bar`

first and then `Foo`

.

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

This way the native instance for `Show[List]`

would be used.

### Type class support matrix

Legend:

`∀`

- all must satisfy a constraint`∃`

- at lest one must satisfy a constraint`∃!`

- exactly one must satisfy a constraint`∧`

- both constraints must be satisfied`∨`

- either constraint must be satisfied

#### For monomorphic types

Type Class | Case Classes | Sealed Traits |
---|---|---|

CommutativeMonoid | ∀ fields: CommutativeMonoid | |

CommutativeSemigroup | ∀ fields: CommutativeSemigroup | |

Empty | ∀ fields: Empty | ∃ variant: Empty |

Eq | ∀ fields: Eq | ∀ variants: Eq |

Hash | ∀ fields: Hash | ∀ variants: Hash |

Monoid | ∀ fields: Monoid | |

Order | ∀ fields: Order | ∃! variant: Order |

PartialOrder | ∀ fields: PartialOrder | ∀ variants: PartialOrder |

Semigroup | ∀ fields: Semigroup | |

Show | ∀ fields: Show | ∀ variants: Show |

ShowPretty | ∀ fields: ShowPretty | ∀ variants: ShowPretty |

#### For polymorphic types

Type Class | Case Classes | Sealed Traits | Constant Types `λ[x => T]` |
Nested Types `λ[x => F[G[x]]]` |
---|---|---|---|---|

Applicative | ∀ fields: Applicative | for T: Monoid | for F: Applicative and G: Applicative | |

Apply | ∀ fields: Apply | for T: Semigroup | for F: Apply and G: Apply | |

Contravariant | ∀ fields: Contravariant | ∀ variants: Contravariant | for any T | for F: Functor and G: Contravariant |

EmptyK | ∀ fields: EmptyK | for T: Empty | for F: EmptyK and any G ∨ for F: Pure and G: EmptyK | |

Foldable | ∀ fields: Foldable | ∀ variants: Foldable | for any T | for F: Foldable and G: Foldable |

Functor | ∀ fields: Functor | ∀ variants: Functor | for any T | for F: Functor and G: Functor ∨ for F: Contravariant and G: Contravariant |

Invariant | ∀ fields: Invariant | ∀ variants: Invariant | for any T | for F: Invariant and G: Invariant |

MonoidK | ∀ fields: MonoidK | for T: Monoid | for F: MonoidK and any G ∨ for F: Applicative and G: MonoidK | |

NonEmptyTraverse | ∃ field: NonEmptyTraverse ∧ ∀ fields: Traverse | ∀ variants: NonEmptyTraverse | for F: NonEmptyTraverse and G: NonEmptyTraverse | |

Pure | ∀ fields: Pure | for T: Empty | for F: Pure and G: Pure | |

Reducible | ∃ field: Reducible ∧ ∀ fields: Foldable | ∀ variants: Reducible | for F: Reducible and G: Reducible | |

SemigroupK | ∀ fields: SemigroupK | for T: Semigroup | for F: SemigroupK and any G ∨ for F: Apply and G: SemigroupK | |

Traverse | ∀ fields: Traverse | ∀ variants: Traverse | for any T | for F: Traverse and G: Traverse |

## Participation

The Kittens project supports the Scala code of conduct and wants all of its channels (mailing list, Gitter, GitHub, etc.) to be welcoming environments for everyone.

## Building kittens

Kittens is built with SBT 1.x, and its master branch is built with Scala 2.13 by default.

## Contributors

- Cody Allen ceedubs@gmail.com @fourierstrick
- Georgi Krastev joro.kr.21@gmail.com @Joro_Kr
- Fabio Labella fabio.labella2@gmail.com @SystemFw
- Miles Sabin miles@milessabin.com @milessabin
- Qi Wang Qi77Qi
- Kailuo Wang kailuo.wang@gmail.com @kailuowang
- Your name here :-)