kittens: automatic type class derivation for Cats and generic utility functions
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 some utility functions related to cats.Applicative such as lift, traverse and sequence to HList, Record and arbitrary parameter list.
kittens is part of the Typelevel family of projects. It is an Open Source project under the Apache License v2, hosted on github. Binary artefacts will be published to the Sonatype OSS Repository Hosting service and synced to Maven Central.
It is current in a pre-alpha state, but should be ready for an initial release in the very near future.
Auto derived Examples
scala> import cats.derived._, functor._, legacy._ scala> import cats.Functor scala> case class Cat[Food](food: Option[Food], foods: List[Food]) defined class Cat scala> val f = Functor[Cat] f: cats.Functor[Cat] = cats.derived.MkFunctor2$$anon$4@782b2ad1 scala> val cat = Cat(Some(1), List(2, 3)) cat: Cat[Int] = Cat(Some(1),List(2, 3)) scala> f.map(cat)(_ + 1) res3: Cat[Int] = Cat(Some(2),List(3, 4))
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 but you need a Poly.
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)
kittens and Typelevel Scala
Typelevel Scala provides a partial fix for SI-7046 which can present obstacles to the uses of
LabelledGeneric for the sealed trait at the root of an ADT such as you find in Kittens. If
it appears that these two type classes are unable to find (all of) the subclasses of an ADT root trait then please try
using Typelevel Scala and see if it resolves the issue.
To use Typelevel Scala you should,
project/build.propertiesto require SBT 0.13.13-M1 or later,
Add the following to your
build.sbtimmediately next to where you set
scalaOrganization := "org.typelevel"
If this does resolve the problem, please lend your support to the pull request being merged in Lightbend Scala.
kittens is built with SBT 0.13.9 or later, and its master branch is built with Scala 2.11.7 by default.