Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/softwaremill/magnolia
Easy, fast, transparent generic derivation of typeclass instances
https://github.com/softwaremill/magnolia
datatypes derives-typeclasses generic-derivation generic-programming implicit-search magnolia-derivation scala typeclass typeclass-derivation typeclasses
Last synced: 6 days ago
JSON representation
Easy, fast, transparent generic derivation of typeclass instances
- Host: GitHub
- URL: https://github.com/softwaremill/magnolia
- Owner: softwaremill
- License: apache-2.0
- Created: 2017-06-06T21:43:05.000Z (over 7 years ago)
- Default Branch: scala3
- Last Pushed: 2024-12-01T00:16:50.000Z (24 days ago)
- Last Synced: 2024-12-12T05:05:58.544Z (13 days ago)
- Topics: datatypes, derives-typeclasses, generic-derivation, generic-programming, implicit-search, magnolia-derivation, scala, typeclass, typeclass-derivation, typeclasses
- Language: Scala
- Homepage: https://softwaremill.com/open-source/
- Size: 1.97 MB
- Stars: 769
- Watchers: 46
- Forks: 117
- Open Issues: 71
-
Metadata Files:
- Readme: readme.md
- License: license.md
Awesome Lists containing this project
README
![Magnolia](https://github.com/softwaremill/magnolia/raw/scala3/banner.jpg)
[](https://github.com/softwaremill/magnolia/actions)
[](https://softwaremill.community/c/magnolia)
[](https://index.scala-lang.org/softwaremill/magnolia/magnolia)# 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,
```scala
enum Tree[+T] derives Print:
case Branch(left: Tree[T], right: Tree[T])
case Leaf(value: T)
```
and provided a given instance of `Print[Int]` is in scope, and a Magnolia derivation for the `Print` typeclass
has been provided, we can automatically derive given typeclass instances of `Print[Tree[Int]]` on-demand, like
so,
```scala
Tree.Branch(Tree.Branch(Tree.Leaf(1), Tree.Leaf(2)), Tree.Leaf(3)).print
```
Typeclass authors may provide Magnolia derivations in the typeclass's companion object, but it is easy to create
your own.Creating a generic derivation with Magnolia requires implementing two methods on `magnolia1.Derivation`:
* `join()` : create typeclasses for case classes ('product types')
* `split()` : create typeclasses for sealed-traits/enums ('sum types')### Example derivations
There are many examples in the [`examples`](examples/src/main/scala/magnolia1/examples) sub-project.
The definition of a `Print` typeclass with generic derivation might look like this
(note we're using the [Lambda syntax for Single Abstract Method types](https://www.scala-lang.org/news/2.12.0/#lambda-syntax-for-sam-types)
to instantiate the `Print` instances in `join` & `split` - that's possible because
`Print` has only a single abstract method, `print`):
```scala
import magnolia1.*trait Print[T] {
extension (x: T) def print: String
}object Print extends AutoDerivation[Print]:
def join[T](ctx: CaseClass[Print, T]): Print[T] = value =>
ctx.params.map { param =>
param.typeclass.print(param.deref(value))
}.mkString(s"${ctx.typeInfo.short}(", ",", ")")override def split[T](ctx: SealedTrait[Print, T]): Print[T] = value =>
ctx.choose(value) { sub => sub.typeclass.print(sub.cast(value)) }
given Print[Int] = _.toString
```The `AutoDerivation` trait provides a given `autoDerived` method which will attempt to construct a corresponding typeclass
instance for the type passed to it. Importing `Print.autoDerived` as defined in the example above will make generic
derivation for `Print` 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.If you don't want to make the automatic derivation available in the given scope, consider using the `Derivation` trait which provides semi-auto derivation with `derived` method, but also brings some additional limitations.
## LimitationsFor accessing default values for case class parameters we recommend compilation with `-Yretain-trees` on.
For a recursive structures it is required to assign the derived value to an implicit variable e.g.
```Scala
given instance: SemiPrint[Recursive] = SemiPrint.derived
```
## AvailabilityFor Scala 3:
```scala
val magnolia = "com.softwaremill.magnolia1_3" %% "magnolia" % "1.3.8"
```For Scala 2, see the [scala2 branch](https://github.com/softwaremill/magnolia/tree/scala2).
## Package and artifact naming, versioning
The main magnolia package is `magnolia1`, so that magnolia 1.x can be used alongside magnolia 0.17 (which are binary-incompatible).
Future major releases of magnolia can change the package name for the same reason.The group id for magnolia follows the naming scheme: `com.softwaremill.magnolia[major version]_[scala major version]`.
The scala major version suffix is necessary to allow evolving and publishing versions for Scala 2 & Scala 3 independently.
The magnolia major version is included for consistency with the package name, and so that future major releases may be
used alongside this release.## Contributing
Contributors to Magnolia are welcome and encouraged. New contributors may like to look for issues marked
.## Credits
Magnolia was originally designed and developed by [Jon Pretty](https://github.com/propensive), and is currently
maintained by [SoftwareMill](https://softwaremill.com).## License
Magnolia is made available under the [Apache 2.0 License](/license.md).