Magnolia

About

Magnolia is a generic macro for automatic materialization of typeclasses for
datatypes composed from case classes (products) and sealed traits
(coproducts). It supports recursively-defined datatypes out-of-the-box, and
incurs no significant time-penalty during compilation. If derivation fails,
error messages are detailed and informative.

Usage

and provided an implicit instance of Show[Int] is in scope, and a Magnolia
derivation for the Show typeclass has been provided, we can
automatically derive an implicit typeclass instance 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 gen method will attempt to construct a typeclass for the type passed to
it. Importing ShowDerivation.gen from the example above will make generic
derivation for Show typeclasses available in the scope of the import. The
macro Magnolia.gen[T] binding must be made in a static object, and the type
constructor, Typeclass, and the methods combine and dispatch must be
defined in the same object.

If you control the typeclass you are deriving for, the companion object of the
typeclass makes a good choice for providing the implicit derivation methods
described above.

Debugging

Deriving typeclasses is not always guaranteed to succeed, though. Many
datatypes are complex and deeply-nested, and failure to derive a typeclass for
a single parameter in one of the leaf nodes will cause the entire tree to fail.

Magnolia tries to be informative about why failures occur, by providing a
”stack trace” showing the path to the type which could not be derived.

For example, when attempting to derive a Show instance for Entity, given
the following hypothetical datatypes,

the absence, for example, of a Show[Boolean] typeclass instance would cause
derivation to fail, but the reason might not be obvious, so instead, Magnolia
will report the following compile error:

could not derive Show instance for type Boolean
in parameter 'salesTax' of product type Country
in parameter 'country' of product type Address
in parameter 'address' of product type Person
in chained implicit of type Set[Person]
in parameter 'contacts' of product type Organization
in coproduct type Entity

This “derivation stack trace” will only be displayed when invoking a derivation
method, e.g. Show.gen[Entity], directly. When the method is invoked through
implicit search, to reduce spurious error messages (when Magnolia’s derivation
fails, but implicit search still finds a valid implicit) the errors are not
shown.

Current Status

Magnolia is currently experimental. It has been shown to work for a variety of
test cases, though it has not had the same exposure to real-world datatypes
that, for example, Shapeless has
had.

The API for defining derivations has been shown to be adequate for the test
cases, and is not expected to change significantly, but some convenience
methods may be provided in the future.

In terms of production-readiness, the macro will not produce code which fails
to typecheck. But it can still refuse to generate a derivation, so users
should be cautious of becoming reliant upon it until it has received more
thorough testing.

However, should Magnolia fail, in all cases it should be possible to write
typeclass instances manually, and have these take precedence.

Macro-based generic derivation is known to be quite heavy on compile times, and
significant effort has been invested in trying to minimize the work Magnolia
does in deriving a typeclass. Preliminary testing comparing Magnolia with
Shapeless suggests that Magnolia
offers between a 4x and 15x performance improvement over Shapeless, depending
on the structure of the ADT being derived.

The runtime performance of Magnolia-generated code has not been tested, and
while some work has gone into minimizing the amount of runtime heap allocations
from generate typeclasses, it is known that it will generate some ephemeral
garbage, and this is an area which is expected to see some improvement in
subsequent versions.