Skip to content
main
Switch branches/tags
Go to file
Code

Files

Permalink
Failed to load latest commit information.
Type
Name
Latest commit message
Commit time
Apr 23, 2021
doc
Apr 17, 2021
src
Apr 23, 2021
Nov 5, 2020
Nov 5, 2020
Nov 5, 2020
Dec 9, 2020
Nov 5, 2020
Apr 17, 2021

GitHub Workflow

Magnolia

Magnolia is a generic macro for automatic materialization of typeclasses for datatypes composed from product types (e.g. case classes) and coproduct types (e.g. enums). It supports recursively-defined datatypes out-of-the-box, and incurs no significant time-penalty during compilation.

Features

  • derives typeclasses for case classes, case objects and sealed traits
  • offers a lightweight syntax for writing derivations without needing to understand complex parts of Scala
  • builds upon Scala 3's built-in generic derivation
  • works with recursive and mutually-recursive definitions
  • supports parameterized ADTs (GADTs), including those in recursive types
  • supports typeclasses whose generic type parameter is used in either covariant and contravariant positions

Getting Started

Given an ADT such as,

enum Tree[+T]:
  case class Branch(left: Tree[T], right: Tree[T])
  case class Leaf(value: T)

and provided an given instance of Show[Int] is in scope, and a Magnolia derivation for the Show typeclass has been provided, we can automatically derive given typeclass instances of Show[Tree[Int]] on-demand, like so,

Branch(Branch(Leaf(1), Leaf(2)), Leaf(3)).show

Typeclass authors may provide Magnolia derivations in the typeclass's companion object, but it is easy to create your own.

The definition of a Show typeclass with generic derivation defined with Magnolia might look like this:

import magnolia.*

trait Show[T]:
  def show(value: T): String

object Show extends Derivation[Show]:
  def join[T](ctx: CaseClass[Show, T]): Show[T] =
    ctx.params.map { p =>
      s"${p.label}=${p.typeclass.show(p.dereference(value))}"
    }.mkString("{", ",", "}")

  override def split[T](ctx: SealedTrait[Show, T]): Show[T] = value =>
    ctx.dispatch(value) { sub => sub.typeclass.show(sub.cast(value))

The Derivation trait provides a derived method which will attempt to construct a corresponding typeclass instance for the type passed to it. Importing Show.derived as defined in the example above will make generic derivation for Show typeclasses available in the scope of the import.

While any object may be used to define a derivation, if you control the typeclass you are deriving for, the companion object of the typeclass is the obvious choice since it generic derivations for that typeclass will be automatically available for consideration during contextual search.

Limitations

Magnolia is not currently able to access default values for case class parameters.

Status

Magnolia is classified as maturescent. Propensive defines the following five stability levels for open-source projects:

  • embryonic: for experimental or demonstrative purposes only, without guarantee of longevity
  • fledgling: of proven utility, seeking contributions, but liable to significant redesigns
  • maturescent: major design decisions broady settled, seeking probatory adoption and refinement of designs
  • dependable: production-ready, subject to controlled ongoing maintenance and enhancement; tagged as version 1.0 or later
  • adamantine: proven, reliable and production-ready, with no further breaking changes ever anticipated

Availability

Magnolia’s source is available on GitHub, and may be built with Fury by cloning the layer propensive/magnolia.

fury layer clone -i propensive/magnolia

or imported into an existing layer with,

fury layer import -i propensive/magnolia

A binary is available on Maven Central as com.propensive:magnolia-core_<scala-version>:2.0.0. This may be added to an sbt build with:

libraryDependencies += "com.propensive" %% "magnolia-core" % "2.0.0"

Contributing

Contributors to Magnolia are welcome and encouraged. New contributors may like to look for issues marked label: good first issue.

We suggest that all contributors read the Contributing Guide to make the process of contributing to Magnolia easier.

Please do not contact project maintainers privately with questions, as other users cannot then benefit from the answers.

Author

Magnolia was designed and developed by Jon Pretty, and commercial support and training is available from Propensive OÜ.

License

Magnolia is copyright © 2018-21 Jon Pretty & Propensive OÜ, and is made available under the Apache 2.0 License.