Skip to content

propensive/wisteria

main
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Code

Latest commit

 

Git stats

Files

Permalink
Failed to load latest commit information.
Type
Name
Latest commit message
Commit time
doc
 
 
src
 
 
 
 
 
 
 
 

GitHub Workflow

Wisteria

Simple, fast and transparant generic derivation for typeclasses

Wisteria 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

Availability

Wisteria has not yet been published as a binary.

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 Wisteria 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 Wisteria 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 Wisteria might look like this:

import wisteria.*

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

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

Status

Wisteria is classified as fledgling. For reference, Scala One projects are categorized into one of the following five stability levels:

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

Projects at any stability level, even embryonic projects, are still ready to be used, but caution should be taken if there is a mismatch between the project's stability level and the importance of your own project.

Wisteria is designed to be small. Its entire source code currently consists of 858 lines of code.

Building

Wisteria can be built on Linux or Mac OS with Fury, however the approach to building is currently in a state of flux, and is likely to change.

Contributing

Contributors to Wisteria are welcome and encouraged. New contributors may like to look for issues marked beginner.

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

Please do not contact project maintainers privately with questions unless there is a good reason to keep them private. While it can be tempting to repsond to such questions, private answers cannot be shared with a wider audience, and it can result in duplication of effort.

Author

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

Name

Wisteria is a flowering plant, much like magnolia is, and Wisteria is a derivative of Magnolia.

In general, Scala One project names are always chosen with some rationale, however it is usually frivolous. Each name is chosen for more for its uniqueness and intrigue than its concision or catchiness, and there is no bias towards names with positive or "nice" meanings—since many of the libraries perform some quite unpleasant tasks.

Names should be English words, though many are obscure or archaic, and it should be noted how willingly English adopts foreign words. Names are generally of Greek or Latin origin, and have often arrived in English via a romance language.

License

Wisteria is copyright © 2023 Jon Pretty & Propensive OÜ, and is made available under the Apache 2.0 License.

About

Easy, fast, transparent generic derivation of typeclass instances in Scala

Topics

Resources

License

Stars

Watchers

Forks