GithubHelp home page GithubHelp logo

kyri-petrou / magnolia Goto Github PK

View Code? Open in Web Editor NEW

This project forked from softwaremill/magnolia

0.0 0.0 0.0 1.77 MB

Easy, fast, transparent generic derivation of typeclass instances

Home Page: https://softwaremill.com/open-source/

License: Apache License 2.0

Java 0.34% Scala 99.66%

magnolia's Introduction

Magnolia

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] 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,

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 src/examples folder.

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 to instantiate the Print instances in join & split - that's possible because Print has only a single abstract method, print):

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.

Limitations

Accessing default values for case class parameters requires compilation with -Yretain-trees on.

For a recursive structures it is required to assign the derived value to an implicit variable e.g.

given instance: SemiPrint[Recursive] = SemiPrint.derived

Availability

For Scala 3:

val magnolia = "com.softwaremill.magnolia1_3" %% "magnolia" % "1.3.3"

For Scala 2, see the scala2 branch.

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 label: good first issue.

Credits

Magnolia was originally designed and developed by Jon Pretty, and is currently maintained by SoftwareMill.

License

Magnolia is made available under the Apache 2.0 License.

magnolia's People

Contributors

adamw avatar fommil avatar ghostbuster91 avatar irevive avatar jatcwang avatar jodersky avatar jorokr21 avatar jto avatar kacperfkorban avatar katlasik avatar kciesielski avatar kevinwright avatar krzemin avatar kubinio123 avatar leandrob13 avatar mbore avatar mergify[bot] avatar micsza avatar note avatar olegych avatar pask423 avatar propensive avatar rafalsumislawski avatar rtyley avatar ruippeixotog avatar scala-steward avatar shadaj avatar sirthias avatar sksamuel avatar xuwei-k avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.