• Stars
    star
    522
  • Rank 81,469 (Top 2 %)
  • Language
    Scala
  • License
    Apache License 2.0
  • Created almost 9 years ago
  • Updated about 2 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Automatic type class derivation for Cats

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 image

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 and 2.13, Scala.js 1.5 and Scala Native 0.4.

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

libraryDependencies += "org.typelevel" %% "kittens" % "latestVersion" // indicated in the badge below

Typelevel library Build status Gitter channel Scala.js Latest version

Scala 2

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

Derive Functor

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

Derive Show

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:

  1. full auto:
import derived.auto.show._

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

  1. 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.

  1. 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.

Scala 3

We also offer 3 methods of derivation for Scala 3. All of them have the same behaviour wrt to recursively defining instances:

  1. Instances will always be recursively instantiated if necessary
  2. Subject to the same type constructor field limitation as the Scala 2 auto and manual semi derivations

derives syntax (recommended)

Kittens for scala 3 supports Scala 3's derivation syntax.

import cats.derived.*

// No instances declared for Name
case class Name(value: String)
case class Person(name: Name, age: Int) derives Eq, Show

enum CList[+A] derives Functor:
  case CNil
  case CCons(head: A, tail: CList[A])

semiauto derivation

This looks similar to semiauto for Scala 2.

import cats.derived.semiauto

// No instances declared for Name
case class Name(value: String)
case class Person(name: Name, age: Int)

object Person:
  given Eq[Person] = semiauto.eq
  given Show[Person] = semiauto.show

enum CList[+A]:
  case CNil
  case CCons(head: A, tail: CList[A])
  
object CList:
  given Functor[CList] = semiauto.functor

As with Scala 2, you can combine auto and semiauto to avoid the type constructor field limitation:

import cats.derived.*

case class Name(value: String)
case class Person(name: Name, age: Int)

case class People(people: List[Person])
object People:
  given Show[People] =
    import auto.show.given
    // Uses the correct List instance despite deriving an instance for Person automatically
    semiauto.show

`

auto derivation

This looks similar to auto for Scala 2.

import cats.derived.auto.eq.given
import cats.derived.auto.show.given
import cats.derived.auto.functor.given

case class Name(value: String)
case class Person(name: Name, age: Int)

enum CList[+A]:
  case CNil
  case CCons(head: A, tail: CList[A])

Caveats

Nested type constructors

We are currently unable to derive instances for nested type constructors, such as Functor[[x] =>> List[Set[x]]].

Stack safety

Our derived instances are not stack-safe. This is a departure from the behaviour for Scala 2 because we didn't want to incur the performance penalty of trampolining all instances in cats.Eval. If your data-type is recursive or extremely large then you may want to write instances by hand instead.

Missing features

Kittens for Scala 3 is built on top of Shapeless 3 which has a completely different API than Shapeless 2 so we don't support features like Sequence and Lift.

ConsK derivation is also not supported although we expect this to be added in a future release.

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

More Repositories

1

cats

Lightweight, modular, and extensible library for functional programming.
Scala
5,120
star
2

fs2

Compositional, streaming I/O library for Scala
Scala
2,319
star
3

scalacheck

Property-based testing for Scala
Scala
1,908
star
4

cats-effect

The pure asynchronous runtime for Scala
Scala
1,817
star
5

spire

Powerful new number types and numeric abstractions for Scala.
Scala
1,753
star
6

skunk

A data access library for Scala + Postgres.
Scala
1,545
star
7

simulacrum

First class syntax support for type classes in Scala
Scala
936
star
8

squants

The Scala API for Quantities, Units of Measure and Dimensional Analysis
Scala
910
star
9

kind-projector

Compiler plugin for making type lambdas (type projections) easier to write
Scala
906
star
10

frameless

Expressive types for Spark.
Scala
869
star
11

cats-collections

Data structures for pure functional programming in Scala
Scala
557
star
12

jawn

Jawn is for parsing jay-sawn (JSON)
Scala
431
star
13

log4cats

Logging Tools For Interaction with cats-effect
Scala
390
star
14

Laika

Site and E-book Generator and Customizable Text Markup Transformer for sbt, Scala and Scala.js
Scala
387
star
15

algebra

Experimental project to lay out basic algebra type classes
Scala
379
star
16

mouse

A small companion to cats
Scala
347
star
17

sbt-tpolecat

scalac options for the enlightened
Scala
328
star
18

discipline

Flexible law checking for Scala
Scala
322
star
19

natchez

functional tracing for cats
Scala
317
star
20

cats-mtl

cats transformer type classes.
Scala
304
star
21

cats-tagless

Library of utilities for tagless final encoded algebras
Scala
301
star
22

CT_from_Programmers.scala

Scala sample code for Bartosz Milewski's CT for Programmers
Scala
279
star
23

fs2-grpc

gRPC implementation for FS2/cats-effect
Scala
258
star
24

cats-parse

A parsing library for the cats ecosystem
Scala
224
star
25

machinist

Spire's macros for zero-cost operator enrichment
Scala
191
star
26

cats-effect-testing

Integration between cats-effect and test frameworks
Scala
184
star
27

paiges

an implementation of Wadler's a prettier printer
Scala
183
star
28

shapeless-3

Generic programming for Scala
Scala
168
star
29

grackle

Grackle: Functional GraphQL for the Typelevel stack
Scala
164
star
30

sbt-typelevel

Let sbt work for you.
Scala
151
star
31

feral

Feral cats are homeless, feral functions are serverless
Scala
144
star
32

munit-cats-effect

Integration library for MUnit & cats-effect
Scala
142
star
33

catbird

Birds and cats together
Scala
140
star
34

otel4s

An OpenTelemetry library for Scala based on Cats-Effect
Scala
138
star
35

fs2-chat

Sample project demonstrating use of fs2-io to build a chat client and server
Scala
123
star
36

spotted-leopards

Proof of concept for a cats-like library built using Dotty features
Scala
112
star
37

fabric

Object-Notation Abstraction for JSON, binary, HOCON, etc.
Scala
110
star
38

literally

Compile time validation of literal values built from strings
Scala
102
star
39

toolkit

Quickstart your next app with the Typelevel Toolkit!
Scala
92
star
40

cats-time

Cats Instances for Java Time
Scala
91
star
41

typelevel-nix

Development tools for Typelevel projects
Nix
87
star
42

vault

Type-safe, persistent storage for values of arbitrary types
Scala
81
star
43

shapeless-contrib

Interoperability libraries for Shapeless
Scala
79
star
44

cats-effect-cps

An incubator project for async/await syntax support for Cats Effect
Scala
78
star
45

scalacheck-effect

Effectful property testing built on ScalaCheck
Scala
76
star
46

coop

Cooperative multithreading as a pure monad transformer
Scala
68
star
47

claimant

Library to support automatic labeling of ScalaCheck properties.
Scala
68
star
48

typeclassic

Everything you need to make type classes first class.
Scala
61
star
49

scalaz-contrib

Interoperability libraries & additional data structures and instances for Scalaz
Scala
55
star
50

twiddles

Micro-library for building effectful protocols
Scala
55
star
51

monoids

Generic Monoids for Scala
Scala
51
star
52

fs2-netty

What it says on the tin!
Scala
47
star
53

sbt-catalysts

sbt utilities for open source projects
Scala
45
star
54

natchez-http4s

Glorious integration layer for Natchez and Http4s.
Scala
44
star
55

typelevel.github.com

Web site of typelevel.scala
HTML
38
star
56

jawn-fs2

Integration between jawn and fs2
Scala
36
star
57

keypool

A Keyed Pool Implementation for Scala
Scala
34
star
58

scalaz-specs2

Specs2 bindings for Scalaz
Scala
34
star
59

catalysts

Scala
34
star
60

case-insensitive

A case-insensitive string for Scala
Scala
34
star
61

simulacrum-scalafix

Simulacrum as Scalafix rules
Scala
33
star
62

scalaz-outlaws

outcasts no longer allowed in the ivory tower
Scala
28
star
63

scalac-options

A library for configuring scalac options
Scala
27
star
64

bobcats

Typelevel's very own CryptoKitties!
Scala
27
star
65

ce3.g8

Scala
24
star
66

scalaz-scalatest

Scalatest bindings for scalaz.
Scala
23
star
67

general

Repository for general Typelevel information, activity and issues
19
star
68

discipline-munit

MUnit binding for Typelevel Discipline
Scala
18
star
69

unique

Unique Functional Values for Scala
Scala
18
star
70

cats-testkit-scalatest

Cats Testkit for Scalatest
Scala
18
star
71

discipline-scalatest

ScalaTest binding for Discipline
Scala
17
star
72

typelevel-scalafix

Scalafix rules for Typelevel projects
Scala
17
star
73

semigroups

Scala
16
star
74

cats-effect-shell

Command line debugging console for Cats Effect
Scala
15
star
75

jdk-index

A Jabba compatible index of JDK versions
Scala
14
star
76

cats-uri

URI implementation based on cats-parse with cats instances
Scala
14
star
77

typelevel.g8

A typelevel.g8 based on sbt-typelevel
Scala
14
star
78

catapult

Scala
13
star
79

weaver-test

A test framework that runs everything in parallel.
Scala
11
star
80

discipline-specs2

Specs2 Integration for Discipline
Scala
8
star
81

governance

Typelevel governance
Scala
7
star
82

catz-cradle

Testbed for scala libraries and tools, based on examples from cats docs
Scala
7
star
83

spire-contrib

Interoperability libraries for spire
Shell
7
star
84

idna4s

Cross-platform Scala implementation of Internationalized Domain Names in Applications
Scala
6
star
85

scalac-compat

Lightweight tools for tackling Scalac version incompatibilities
Scala
6
star
86

steward

Runs Scala Steward for Typelevel projects
5
star
87

cats-effect-main

3
star
88

sacagawea

Common infrastructure for tracing functional effects
Scala
3
star
89

scalacheck-xml

Scalacheck instances for scala-xml
Scala
3
star
90

sorcery

WIP
2
star
91

scalacheck-web

ScalaCheck Web Site
Nix
2
star
92

sbt-catalysts.g8

Scala
2
star
93

feral.g8

Giter8 template for feral serverless
Scala
2
star
94

download-java

2
star
95

toolkit.g8

A Giter8 template for Typelevel Toolkit!
Scala
2
star
96

sbt-tls-crossproject

sbt-crossproject plugin for Typelevel Scala
Scala
1
star
97

catalysts-docker

Shell
1
star
98

await-cirrus

Depend on Cirrus CI from a GitHub Actions workflow
JavaScript
1
star
99

.github

a ✨special ✨ repository for project defaults and organization readme
1
star