Git Product home page Git Product logo

hs-wrapped's Introduction

wrapped

A single standardized place to hang DerivingVia instances.

Stack CI

Disclaimer

This is not an officially supported Google product.

Hackage Status

  • wrapped Uploaded Haddock
  • wrapped-generic-default Uploaded Haddock

Overview

GHC.Generics provides a great mechanism for deriving instances of many classes for many types, but the ergonomics of opting into the derived instances could be better. Currently, functionality derived from other classes is often exported only as free-standing functions implementing the methods of a class, or as default methods in the class definition itself.

The former means you have to define an instance by hand to plug the derived implementations into the methods:

data MyType a = ...

instance Distributive MyType where
  collect = collectRep
  distribute = distributeRep

The latter means you must either define an empty instance or use DeriveAnyClass, neither of which is particularly clear about how the class will be implemented:

data MyType a = ...
  deriving Generic
  deriving anyclass Representable

-- or:
-- instance Representable MyType

This package attempts to improve this situation, taking advantage of DerivingVia. It provides a type on which to hang instances of arbitrary classes derived from arbitrary classes, so that derived instances can all be accessed uniformly with DerivingVia. The desired outcome would be to support usage like this:

data MyType a = ...
  deriving stock (Generic, Functor, Foldable, Traversable, Show)
  deriving (Portray, Semigroup, Monoid) via Wrapped Generic (MyType a)
  deriving Representable via Wrapped1 Generic1 MyType
  deriving Distributive via Wrapped1 Representable MyType

In reality, prohibition of orphan instances gets in the way: the adjunctions and distributive packages don't provide the instances for Wrapped themselves, and it's not feasible to have wrapped depend on every package that provides derived instances. So, the aim is to make wrapped as lightweight as possible (it depends only on base), so that library maintainers can depend on it to provide instances for the classes they define, or instances derived from the classes they define.

Caveats

Type Roles

Some classes (e.g. Distributive and Traversable) cannot work with DerivingVia as currently defined, because they mention the instance type under a type constructor that's not known to have representational role, so their methods can't be coerced to the desired type.

See https://ryanglscott.github.io/2018/06/22/quantifiedconstraints-and-the-trouble-with-traversable/ for a discussion of this issue and a technique for working around it.

Superclasses

DerivingVia has some potentially-surprising or frustrating behavior related to superclasses.

Firstly, when deriving an instance for a class with a superclass (e.g. Monoid), the superclass instance is not derived along with it, so the type is free to provide its own instance. But, if the methods of the subclass subsume the functionality of the superclass (like mappend), those methods will still come from the DerivingVia, resulting in (for example) a Monoid whose mappend is different from <> on the same type. One might reasonably assume that deriving Monoid for a type with a custom Semigroup instance would be equivalent to writing instance Monoid MyType where mempty = genericMempty, but there's an invisible default definition of mappend in the DerivingVia case that uses the <> of the via type, not the original type.

Secondly (relatedly), providing an instance on Wrapped this way requires satisfying its superclasses: to provide a Representable instance, I have to arrange for Wrapped to have a Functor instance along with it; if there's such an instance derived from Generic, then I have to include its context in the context of the Representable instance, too. Even worse, this can mean it's impossible to provide instances for classes you've just defined because their superclasses are classes you didn't define, and they'd be orphan instances.

hs-wrapped's People

Contributors

awpr avatar

Stargazers

 avatar  avatar

Watchers

 avatar  avatar  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.