generic-data: Deriving instances with GHC.Generics and related utilities

[ generics, library, mit ] [ Propose Tags ]

Generic implementations of standard type classes. Operations on generic representations to help using GHC.Generics. See README.


[Skip to Readme]

Flags

Manual Flags

NameDescriptionDefault
enable-inspect

Enable inspection tests (broken on ghc or= 9.2)

Disabled

Use -f <flag> to enable a flag, or -f -<flag> to disable that flag. More info

Downloads

Note: This package has metadata revisions in the cabal description newer than included in the tarball. To unpack the package including the revisions, use 'cabal get'.

Maintainer's Corner

Package maintainers

For package maintainers and hackage trustees

Candidates

Versions [RSS] 0.1.0.0, 0.1.1.0, 0.2.0.0, 0.3.0.0, 0.4.0.0, 0.5.0.0, 0.6.0.0, 0.6.0.1, 0.7.0.0, 0.8.0.0, 0.8.1.0, 0.8.2.0, 0.8.3.0, 0.9.0.0, 0.9.1.0, 0.9.2.0, 0.9.2.1, 1.0.0.0, 1.0.0.1, 1.1.0.0
Change log CHANGELOG.md
Dependencies ap-normalize (>=0.1 && <0.2), base (>=4.9 && <4.21), base-orphans (>=0.8.8), contravariant, ghc-boot-th, show-combinators [details]
License MIT
Copyright 2018-2020 Li-yao Xia
Author Li-yao Xia
Maintainer lysxia@gmail.com
Revised Revision 2 made by lyxia at 2024-03-17T20:09:29Z
Category Generics
Home page https://github.com/Lysxia/generic-data#readme
Source repo head: git clone https://github.com/Lysxia/generic-data
Uploaded by lyxia at 2023-03-14T13:25:10Z
Distributions Arch:1.1.0.0, Debian:0.8.3.0, LTSHaskell:1.1.0.0, NixOS:1.1.0.0, Stackage:1.1.0.0
Reverse Dependencies 14 direct, 236 indirect [details]
Downloads 25846 total (222 in the last 30 days)
Rating 2.0 (votes: 1) [estimated by Bayesian average]
Your Rating
  • λ
  • λ
  • λ
Status Docs available [build log]
Last success reported on 2023-03-14 [all 1 reports]

Readme for generic-data-1.1.0.0

[back to package description]

Generic data types in Haskell Hackage GitHub CI

Utilities for GHC.Generics.

Generic deriving for standard classes

Example: generically deriving Semigroup instances for products

Semi-automatic method using gmappend

data Foo a = Bar [a] [a] deriving Generic

instance Semigroup (Foo a) where
  (<>) = gmappend

This library also synergizes with the DerivingVia extension (introduced in GHC 8.6), thanks to the Generically newtype.

data Foo a = Bar [a] [a]
  deriving Generic
  deriving Semigroup via (Generically (Foo a))

These examples can be found in test/example.hs.


Note for completeness, the first example uses the following extensions and imports:

{-# LANGUAGE DeriveGeneric #-}

-- base
import Data.Semigroup (Semigroup(..))

-- generic-data
import Generic.Data (Generic, gmappend)
import Generic.Data.Orphans ()

The second example makes these additions on top:

{-# LANGUAGE
    DerivingStrategies,
    DerivingVia #-}  -- since GHC 8.6.1

-- In addition to the previous imports
import Generic.Data (Generically(..))

Supported classes

Supported classes that GHC currently can't derive: Semigroup, Monoid, Applicative, Alternative, Eq1, Ord1, Show1.

Other classes from base are also supported, even though GHC can already derive them:

  • Eq, Ord, Enum, Bounded, Show, Read (derivable by the standard);
  • Functor, Foldable, Traversable (derivable via extensions, DeriveFunctor, etc.).

To derive type classes outside of the standard library, it might be worth taking a look at one-liner.

Type metadata

Extract type names, constructor names, number and arities of constructors, etc..

Type surgery

generic-data offers simple operations (microsurgeries) on generic representations.

More surgeries can be found in generic-data-surgery, and suprisingly, in generic-lens and one-liner.

For more details, see also:

  • the module Generic.Data.Microsurgery;

  • the files test/lens-surgery.hs and one-liner-surgery.hs.

Surgery example

Derive an instance of Show generically for a record type, but as if it were not a record.

{-# LANGUAGE DeriveGeneric #-}
import Generic.Data (Generic, gshowsPrec)
import Generic.Data.Microsurgery (toData, derecordify)

-- An example record type
newtype T = T { unT :: Int } deriving Generic

-- Naively deriving Show would result in this being shown:
--
-- show (T 3) = "T {unT = 3}"
--
-- But instead, with a simple surgery, unrecordify, we can forget T was
-- declared as a record:
--
-- show (T 3) = "T 3"

instance Show T where
  showsPrec n = gshowsPrec n . derecordify . toData

-- This example can be found in test/microsurgery.hs

Alternatively, using DerivingVia:

{-# LANGUAGE DeriveGeneric, DerivingVia #-}
import Generic.Data (Generic)  -- Reexported from GHC.Generics

-- Constructors must be visible to use DerivingVia
import Generic.Data.Microsurgery (Surgery, Surgery'(..), Generically(..), Derecordify)

data V = V { v1 :: Int, v2 :: Int }
  deriving Generic
  deriving Show via (Surgery Derecordify V)

-- show (V {v1 = 3, v2 = 4}) = "V 3 4"

generic-data aims to subsume generic deriving features of the following packages:

  • semigroups: generic Semigroup, Monoid, but with a heavier dependency footprint.
  • transformers-compat: generic Eq1, Ord1, Show1.
  • generic-deriving: doesn't derive the classes in base (defines clones of these classes as a toy example); has Template Haskell code to derive Generic (not in generic-data).

Other relevant links.


Internal module policy

Modules under Generic.Data.Internal are not subject to any versioning policy. Breaking changes may apply to them at any time.

If something in those modules seems useful, please report it or create a pull request to export it from an external module.


All contributions are welcome. Open an issue or a pull request on Github!