A collection of Magnolia add-ons for common typeclass derivation, data type conversion, etc.; a simpler and faster successor to shapeless-datatype.
This library includes the following modules.
-
magnolify-cats
- type class derivation for Cats, specifically -
magnolify-scalacheck
- type class derivation for ScalaCheck -
magnolify-guava
- type class derivation for Guava -
magnolify-avro
- conversion between Scala types and Apache AvroGenericRecord
-
magnolify-bigquery
- conversion between Scala types and Google Cloud BigQueryTableRow
-
magnolify-bigtable
- conversion between Scala types and Google Cloud Bigtable toMutation
, fromRow
-
magnolify-datastore
- conversion between Scala types and Google Cloud DatastoreEntity
-
magnolify-protobuf
- conversion between Scala types and Google Protocol BufferMessage
-
magnolify-tensorflow
- conversion between Scala types and TensorFlowExample
Cats, ScalaCheck, and Guava typeclass derivation can be performed both automatically and semi-automatically.
Automatic derivation are provided as implicits through import magnolify.$module.auto._
. It works with context bounds i.e. def plus[T: Semigroup](x: T, y: T)
and implicit paramemters i.e. def f[T](x: T, y: T)(implicit sg: Semigroup[T])
. The following examples summon them via implicitly
.
case class Inner(int: Int, str: String)
case class Outer(inner: Inner)
// Cats Semigroup
import magnolify.cats.auto._
import cats._
import cats.instances.all._ // implicit instances for Semigroup[Int], etc.
val sg: = implicitly[Semigroup[Outer]]
sg.combine(Outer(Inner(1, "hello, ")), Outer(Inner(100, "world!")))
// = Outer(Inner(101,hello, world!))
// ScalaCheck Arbitrary
import magnolify.scalacheck.auto._
import org.scalacheck._ // implicit instances for Arbitrary[Int], etc.
val arb: Arbitrary[Outer] = implicitly[Arbitrary[Outer]]
arb.arbitrary.sample
// = Some(Outer(Inter(12345, abcde)))
// Guava Funnel
import magnolify.guava.auto._ // includes implicit instances for Funnel[Int], etc.
import com.google.common.hash._
val fnl: Funnel[Outer] = implicitly[Funnel[Outer]]
val bf: BloomFilter[Outer] = BloomFilter.create[Outer](fnl, 1000)
Semi-automatic derivation needs to be called explicitly.
import magnolify.cats.semiauto._
import cats._
import cats.instances.all._
val eq: Eq[Outer] = EqDerivation[Outer]
val hash: Hash[Outer] = HashDerivation[Outer]
val sg: Semigroup[Outer] = SemigroupDerivation[Outer]
val mon: Monoid[Outer] = MonoidDerivation[Outer]
// this fails due to missing `Group[String]` instance
val group: Group[Outer] = GroupDerivation[Outer]
import magnolify.scalacheck.semiauto._
import org.scalacheck._
val arb: Arbitrary[Outer] = ArbitraryDerivation[Outer]
val cogen: Cogen[Outer] = CogenDerivation[Outer]
import magnolify.guava.semiauto._
val fnl: Funnel[Outer] = FunnelDerivation[Outer]
Typeclasses for data type conversion must be called explicitly.
import java.net.URI
case class Inner(long: Long, str: String, uri: URI)
case class Outer(inner: Inner)
val record = Outer(Inner(1L, "hello", URI.create("https://www.spotify.com")))
// Avro GenericRecord
import magnolify.avro._
import org.apache.avro.generic.GenericRecord
implicit val uriField = AvroField.from[String](URI.create)(_.toString) // custom field type
val avroType = AvroType[Outer]
val genericRecord: GenericRecord = avroType.to(record)
val copy: Outer = avroType.from(genericRecord)
avroType.schema // Avro Schema
// BigQuery TableRow
import magnolify.bigquery._
import com.google.api.services.bigquery.model.TableRow
implicit val uriField = TableRowField.from[String](URI.create)(_.toString) // custom field type
val tableRowType = TableRowType[Outer]
val tableRow: TableRow = tableRowType.to(record)
val copy: Outer = tableRowType.from(tableRow)
tableRowType.schema // BigQuery TableSchema
// Bigtable Example
import magnolify.bigtable._
implicit val uriField = BigtableField.from[String](URI.create)(_.toString)
val bigtableType = BigtableType[Outer]
val mutations: Iterable[Mutation] = bigtableType(record, "ColumnFamily")
val row: Row = BigtableType.mutationsToRow(ByteString.copyFromUtf8("RowKey"), mutations)
val copy: Outer = bigtableType.from(row, "ColumnFamily")
// Datastore Entity
import magnolify.datastore._
implicit val uriField = EntityField.from[String](URI.create)(_.toString) // custom field type
val entityType = EntityType[Outer]
val entityBuilder: Entity.Builder = entityType.to(record)
val copy: Outer = entityType.from(entityBuilder.build)
// Protobuf
import magnolify.protobuf._
implicit val uriField: ProtobufField[URI] = ProtobufField.from[URI](URI.create)(_.toString)
val protobufType = ProtobufType[Outer, Proto] // Proto is compiled Protobuf Message
val proto: Proto = protobufType.to(record)
val copy: Outer = protobufType.from(proto)
// TensorFlow Example
import magnolify.tensorflow._
import com.google.protobuf.ByteString
// custom field types
implicit val stringField = ExampleField.from[ByteString](_.toStringUtf8)(ByteString.copyFromUtf8)
implicit val uriField = ExampleField
.from[ByteString](b => URI.create(b.toStringUtf8))(u => ByteString.copyFromUtf8(u.toString))
val exampleType = ExampleType[Outer]
val exampleBuilder: Example.Builder = exampleType.to(record)
val copy = exampleType.from(exampleBuilder.build)
Copyright 2019 Spotify AB.
Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0