estatico / generic-traits

Automatic generic derivation for traits

GitHub

Generic Traits

Build Status Gitter Maven Central

Automatic generic derivation for traits

Usage

For traits which are not coproducts (e.g. not part of a sealed trait/case class family), this library allows you to derive shapeless Generic and LabelledGeneric instances from accessor fields. These instances allow us to operate on our traits generically; for instance, we can automatically derive type class instances for them.

Simply importing io.estatico.generic.traits._ will bring in the implicit macro used to derive instances. See the example usage below.

scala> :paste
// Entering paste mode (ctrl-D to finish)

import io.estatico.generic.traits._

trait Foo {
  def bar: String
  def baz: Int
}

// Exiting paste mode, now interpreting.

scala> shapeless.Generic[Foo]
res0: shapeless.Generic[Foo]{type Repr = shapeless.::[String,shapeless.::[Int,shapeless.HNil]]} = $anon$1@38245121

scala> val foo = new Foo { val bar = "a" ; val baz = 1 }
foo: Foo{val bar: String; val baz: Int} = $anon$1@1f0ed694

scala> val repr = shapeless.Generic[Foo].to(foo)
repr: shapeless.::[String,shapeless.::[Int,shapeless.HNil]] = a :: 1 :: HNil

scala> val foo = shapeless.Generic[Foo].from(repr)
foo: Foo = $anon$1$$anon$2@10423297

scala> (foo.bar, foo.baz)
res1: String = (a,1)

scala> shapeless.LabelledGeneric[Foo]
res2: shapeless.LabelledGeneric[Foo]{type Repr = shapeless.::[String with shapeless.labelled.KeyTag[Symbol with shapeless.tag.Tagged[String("bar")],String],shapeless.::[Int with shapeless.labelled.KeyTag[Symbol with shapeless.tag.Tagged
[String("baz")],Int],shapeless.HNil]]} = shapeless.LabelledGeneric$$anon$1@1d3983be

scala> val repr = shapeless.LabelledGeneric[Foo].to(foo)
repr: shapeless.::[String with shapeless.labelled.KeyTag[Symbol with shapeless.tag.Tagged[String("bar")],String],shapeless.::[Int with shapeless.labelled.KeyTag[Symbol with shapeless.tag.Tagged[String("baz")],Int],shapeless.HNil]] = a :
: 1 :: HNil

scala> val foo = shapeless.LabelledGeneric[Foo].from(repr)
foo: Foo = $anon$2$$anon$3@2a03c5d

scala> (res1.bar, res1.baz)
res3: (String, Int) = (a,1)