generic-data-0.9.2.1: Deriving instances with GHC.Generics and related utilities
Safe HaskellNone
LanguageHaskell2010

Generic.Data.Microsurgery

Description

Simple operations on generic representations: modify Generic instances to tweak the behavior of generic implementations as if you had declared a slightly different type.

This module provides the following microsurgeries:

  • RenameFields: rename the fields of a record type.
  • RenameConstrs: rename the constructors.
  • OnFields: apply a type constructor f :: Type -> Type to every field.
  • CopyRep: use the generic representation of another type of the same shape.
  • Typeage: treat a newtype as a data type.
  • Derecordify: treat a type as if it weren't a record.

More complex surgeries can be found in generic-data-surgery but also, perhaps surprisingly, in generic-lens (read more about this just below) and one-liner.

Surgeries can be used:

  • to derive type class instances with the DerivingVia extension, using the Surgery or ProductSurgery type synonyms (for classes with instances for Generically or GenericProduct);
  • with the Data "synthetic type" for more involved transformations, for example using lenses in the next section.
Synopsis

Surgeries with generic-lens

One common and simple situation is to modify the type of some fields, for example wrapping them in a newtype.

We can leverage the generic-lens library, with the two functions below.

-- Lens to a field named fd in a Generic record.
field_ :: HasField_ fd s t a b => Lens s t a b  -- from generic-lens

-- Update a value through a lens (ASetter is a specialization of Lens).
over :: ASetter s t a b -> (a -> b) -> s -> t   -- from lens or microlens

For example, here is a record type:

data R = R { myField :: Int } deriving Generic

The function over (field_ @"myField") Opaque applies the newtype constructor Opaque to the field "myField", but this actually doesn't typecheck as-is. With a bit of help from this module, we can wrap that function as follows:

onData (over (field_ @"myField") Opaque) . toData
  :: R -> Data _ _   -- type arguments hidden

The result has a type Data _ _, that from the point of view of GHC.Generics looks just like R but with the field "myField" wrapped in Opaque, as if we had defined:

data R = R { myField :: Opaque Int } deriving Generic

Example usage

We derive an instance of Show that hides the "myField" field, whatever its type.

instance Show R where
  showsPrec n = gshowsPrec n
    . onData (over (field_ @"myField") Opaque)
    . toData

show (R 3) = "R {myField = _}"

Deriving via

type Surgery (s :: *) (a :: *) = Generically (Surgery' s a) Source #

Apply a microsurgery s to a type a for DerivingVia.

For the Monoid class, see ProductSurgery.

Example

{-# LANGUAGE DerivingVia #-}

-- The constructors must be visible.
import Generic.Data.Microsurgery
  (Surgery, Surgery'(..), Generically(..), Derecordify)

data T = T { unT :: Int }
  deriving Show via (Surgery Derecordify T)

-- T won't be shown as a record:
--   show (T {unT = 3}) == "T 3"

type ProductSurgery (s :: *) (a :: *) = GenericProduct (Surgery' s a) Source #

Apply a microsurgery s to a type a for DerivingVia for the Monoid class.

newtype Surgery' (s :: *) (a :: *) Source #

See Surgery.

Constructors

Surgery' 

Fields

Instances

Instances details
(Generic a, Coercible (GSurgery s (Rep a)) (Rep a)) => Generic (Surgery' s a) Source # 
Instance details

Defined in Generic.Data.Internal.Microsurgery

Associated Types

type Rep (Surgery' s a) :: Type -> Type #

Methods

from :: Surgery' s a -> Rep (Surgery' s a) x #

to :: Rep (Surgery' s a) x -> Surgery' s a #

type Rep (Surgery' s a) Source # 
Instance details

Defined in Generic.Data.Internal.Microsurgery

type Rep (Surgery' s a) = GSurgery s (Rep a)

type family GSurgery (s :: *) (f :: k -> *) :: k -> * Source #

Apply a microsurgery represented by a symbol s (declared as a dummy data type) to a generic representation f.

Instances

Instances details
type GSurgery Derecordify (f :: k -> Type) Source # 
Instance details

Defined in Generic.Data.Internal.Microsurgery

type GSurgery Derecordify (f :: k -> Type) = GDerecordify f
type GSurgery Typeage (M1 D ('MetaData nm md pk _nt) f :: k -> Type) Source # 
Instance details

Defined in Generic.Data.Internal.Microsurgery

type GSurgery Typeage (M1 D ('MetaData nm md pk _nt) f :: k -> Type) = M1 D ('MetaData nm md pk 'False) f
type GSurgery (CopyRep a) (_1 :: Type -> Type) Source # 
Instance details

Defined in Generic.Data.Internal.Microsurgery

type GSurgery (CopyRep a) (_1 :: Type -> Type) = Rep a
type GSurgery (RenameFields rnm) (f :: k -> Type) Source # 
Instance details

Defined in Generic.Data.Internal.Microsurgery

type GSurgery (RenameFields rnm) (f :: k -> Type) = GRenameFields rnm f
type GSurgery (RenameConstrs rnm) (f :: k -> Type) Source # 
Instance details

Defined in Generic.Data.Internal.Microsurgery

type GSurgery (RenameConstrs rnm) (f :: k -> Type) = GRenameConstrs rnm f
type GSurgery (OnFields f) (g :: k -> Type) Source # 
Instance details

Defined in Generic.Data.Internal.Microsurgery

type GSurgery (OnFields f) (g :: k -> Type) = GOnFields f g

newtype Generically a Source #

Type with instances derived via Generic.

Examples

Deriving Eq, Ord, Show, Read

Expand
>>> :{
data T = C Int Bool
  deriving Generic
  deriving (Eq, Ord, Show, Read) via (Generically T)
:}

Deriving Semigroup, Monoid

Expand

The type must have only one constructor.

>>> import Data.Monoid (Sum)
>>> :{
data U = D [Int] (Sum Int)
  deriving Generic
  deriving (Semigroup, Monoid) via (Generically U)
:}

Deriving Enum, Bounded

Expand

The type must have only nullary constructors. To lift that restriction, see FiniteEnumeration.

>>> :{
data V = X | Y | Z
  deriving Generic
  deriving (Eq, Ord, Enum, Bounded) via (Generically V)
:}

Constructors

Generically 

Fields

Instances

Instances details
(Generic a, GBounded (Rep a)) => Bounded (Generically a) Source # 
Instance details

Defined in Generic.Data.Internal.Generically

(Generic a, GEnum StandardEnum (Rep a)) => Enum (Generically a) Source # 
Instance details

Defined in Generic.Data.Internal.Generically

(Generic a, Eq (Rep a ())) => Eq (Generically a) Source # 
Instance details

Defined in Generic.Data.Internal.Generically

(Generic a, Ord (Rep a ())) => Ord (Generically a) Source # 
Instance details

Defined in Generic.Data.Internal.Generically

(Generic a, GRead0 (Rep a)) => Read (Generically a) Source # 
Instance details

Defined in Generic.Data.Internal.Generically

(Generic a, GShow0 (Rep a)) => Show (Generically a) Source # 
Instance details

Defined in Generic.Data.Internal.Generically

(Generic a, Ord (Rep a ()), GIx (Rep a)) => Ix (Generically a) Source # 
Instance details

Defined in Generic.Data.Internal.Generically

Generic a => Generic (Generically a) Source # 
Instance details

Defined in Generic.Data.Internal.Generically

Associated Types

type Rep (Generically a) :: Type -> Type #

Methods

from :: Generically a -> Rep (Generically a) x #

to :: Rep (Generically a) x -> Generically a #

(AssertNoSum Semigroup a, Generic a, Semigroup (Rep a ())) => Semigroup (Generically a) Source # 
Instance details

Defined in Generic.Data.Internal.Generically

(AssertNoSum Semigroup a, Semigroup a, Generic a, Monoid (Rep a ())) => Monoid (Generically a) Source #

This uses the Semigroup instance of the wrapped type a to define mappend. The purpose of this instance is to derive mempty, while remaining consistent with possibly custom Semigroup instances.

Instance details

Defined in Generic.Data.Internal.Generically

type Rep (Generically a) Source # 
Instance details

Defined in Generic.Data.Internal.Generically

type Rep (Generically a) = Rep a

newtype GenericProduct a Source #

Product type with generic instances of Semigroup and Monoid.

This is similar to Generically in most cases, but GenericProduct also works for types T with deriving via GenericProduct U, where U is a generic product type coercible to, but distinct from T. In particular, U may not have an instance of Semigroup, which Generically requires.

Example

Expand
>>> import Data.Monoid (Sum(..))
>>> data Point a = Point a a deriving Generic
>>> :{
  newtype Vector a = Vector (Point a)
    deriving (Semigroup, Monoid)
      via GenericProduct (Point (Sum a))
:}

If it were via Generically (Point (Sum a)) instead, then Vector's mappend (the Monoid method) would be defined as Point's (<>) (the Semigroup method), which might not exist, or might not be equivalent to Vector's generic Semigroup instance, which would be unlawful.

Constructors

GenericProduct 

Fields

Synthetic types

data Data r p Source #

Synthetic data type.

A wrapper to view a generic Rep as the datatype it's supposed to represent, without needing a declaration.

Instances

Instances details
Monad r => Monad (Data r) Source # 
Instance details

Defined in Generic.Data.Internal.Data

Methods

(>>=) :: Data r a -> (a -> Data r b) -> Data r b #

(>>) :: Data r a -> Data r b -> Data r b #

return :: a -> Data r a #

Functor r => Functor (Data r) Source # 
Instance details

Defined in Generic.Data.Internal.Data

Methods

fmap :: (a -> b) -> Data r a -> Data r b #

(<$) :: a -> Data r b -> Data r a #

Applicative r => Applicative (Data r) Source # 
Instance details

Defined in Generic.Data.Internal.Data

Methods

pure :: a -> Data r a #

(<*>) :: Data r (a -> b) -> Data r a -> Data r b #

liftA2 :: (a -> b -> c) -> Data r a -> Data r b -> Data r c #

(*>) :: Data r a -> Data r b -> Data r b #

(<*) :: Data r a -> Data r b -> Data r a #

Foldable r => Foldable (Data r) Source # 
Instance details

Defined in Generic.Data.Internal.Data

Methods

fold :: Monoid m => Data r m -> m #

foldMap :: Monoid m => (a -> m) -> Data r a -> m #

foldMap' :: Monoid m => (a -> m) -> Data r a -> m #

foldr :: (a -> b -> b) -> b -> Data r a -> b #

foldr' :: (a -> b -> b) -> b -> Data r a -> b #

foldl :: (b -> a -> b) -> b -> Data r a -> b #

foldl' :: (b -> a -> b) -> b -> Data r a -> b #

foldr1 :: (a -> a -> a) -> Data r a -> a #

foldl1 :: (a -> a -> a) -> Data r a -> a #

toList :: Data r a -> [a] #

null :: Data r a -> Bool #

length :: Data r a -> Int #

elem :: Eq a => a -> Data r a -> Bool #

maximum :: Ord a => Data r a -> a #

minimum :: Ord a => Data r a -> a #

sum :: Num a => Data r a -> a #

product :: Num a => Data r a -> a #

Traversable r => Traversable (Data r) Source # 
Instance details

Defined in Generic.Data.Internal.Data

Methods

traverse :: Applicative f => (a -> f b) -> Data r a -> f (Data r b) #

sequenceA :: Applicative f => Data r (f a) -> f (Data r a) #

mapM :: Monad m => (a -> m b) -> Data r a -> m (Data r b) #

sequence :: Monad m => Data r (m a) -> m (Data r a) #

Contravariant r => Contravariant (Data r) Source # 
Instance details

Defined in Generic.Data.Internal.Data

Methods

contramap :: (a -> b) -> Data r b -> Data r a #

(>$) :: b -> Data r b -> Data r a #

Eq1 r => Eq1 (Data r) Source # 
Instance details

Defined in Generic.Data.Internal.Data

Methods

liftEq :: (a -> b -> Bool) -> Data r a -> Data r b -> Bool #

Ord1 r => Ord1 (Data r) Source # 
Instance details

Defined in Generic.Data.Internal.Data

Methods

liftCompare :: (a -> b -> Ordering) -> Data r a -> Data r b -> Ordering #

GShow1 r => Show1 (Data r) Source # 
Instance details

Defined in Generic.Data.Internal.Data

Methods

liftShowsPrec :: (Int -> a -> ShowS) -> ([a] -> ShowS) -> Int -> Data r a -> ShowS #

liftShowList :: (Int -> a -> ShowS) -> ([a] -> ShowS) -> [Data r a] -> ShowS #

Alternative r => Alternative (Data r) Source # 
Instance details

Defined in Generic.Data.Internal.Data

Methods

empty :: Data r a #

(<|>) :: Data r a -> Data r a -> Data r a #

some :: Data r a -> Data r [a] #

many :: Data r a -> Data r [a] #

MonadPlus r => MonadPlus (Data r) Source # 
Instance details

Defined in Generic.Data.Internal.Data

Methods

mzero :: Data r a #

mplus :: Data r a -> Data r a -> Data r a #

Generic1 (Data r :: Type -> Type) Source # 
Instance details

Defined in Generic.Data.Internal.Data

Associated Types

type Rep1 (Data r) :: k -> Type #

Methods

from1 :: forall (a :: k). Data r a -> Rep1 (Data r) a #

to1 :: forall (a :: k). Rep1 (Data r) a -> Data r a #

GBounded r => Bounded (Data r p) Source # 
Instance details

Defined in Generic.Data.Internal.Data

Methods

minBound :: Data r p #

maxBound :: Data r p #

GEnum StandardEnum r => Enum (Data r p) Source # 
Instance details

Defined in Generic.Data.Internal.Data

Methods

succ :: Data r p -> Data r p #

pred :: Data r p -> Data r p #

toEnum :: Int -> Data r p #

fromEnum :: Data r p -> Int #

enumFrom :: Data r p -> [Data r p] #

enumFromThen :: Data r p -> Data r p -> [Data r p] #

enumFromTo :: Data r p -> Data r p -> [Data r p] #

enumFromThenTo :: Data r p -> Data r p -> Data r p -> [Data r p] #

Eq (r p) => Eq (Data r p) Source # 
Instance details

Defined in Generic.Data.Internal.Data

Methods

(==) :: Data r p -> Data r p -> Bool #

(/=) :: Data r p -> Data r p -> Bool #

Ord (r p) => Ord (Data r p) Source # 
Instance details

Defined in Generic.Data.Internal.Data

Methods

compare :: Data r p -> Data r p -> Ordering #

(<) :: Data r p -> Data r p -> Bool #

(<=) :: Data r p -> Data r p -> Bool #

(>) :: Data r p -> Data r p -> Bool #

(>=) :: Data r p -> Data r p -> Bool #

max :: Data r p -> Data r p -> Data r p #

min :: Data r p -> Data r p -> Data r p #

(GShow1 r, Show p) => Show (Data r p) Source # 
Instance details

Defined in Generic.Data.Internal.Data

Methods

showsPrec :: Int -> Data r p -> ShowS #

show :: Data r p -> String #

showList :: [Data r p] -> ShowS #

(Functor r, Contravariant r) => Generic (Data r p) Source # 
Instance details

Defined in Generic.Data.Internal.Data

Associated Types

type Rep (Data r p) :: Type -> Type #

Methods

from :: Data r p -> Rep (Data r p) x #

to :: Rep (Data r p) x -> Data r p #

Semigroup (r p) => Semigroup (Data r p) Source # 
Instance details

Defined in Generic.Data.Internal.Data

Methods

(<>) :: Data r p -> Data r p -> Data r p #

sconcat :: NonEmpty (Data r p) -> Data r p #

stimes :: Integral b => b -> Data r p -> Data r p #

Monoid (r p) => Monoid (Data r p) Source # 
Instance details

Defined in Generic.Data.Internal.Data

Methods

mempty :: Data r p #

mappend :: Data r p -> Data r p -> Data r p #

mconcat :: [Data r p] -> Data r p #

type Rep1 (Data r :: Type -> Type) Source # 
Instance details

Defined in Generic.Data.Internal.Data

type Rep1 (Data r :: Type -> Type) = r
type Rep (Data r p) Source # 
Instance details

Defined in Generic.Data.Internal.Data

type Rep (Data r p) = r

toData :: Generic a => a -> Data (Rep a) p Source #

Conversion between a generic type and the synthetic type made using its representation. Inverse of fromData.

fromData :: Generic a => Data (Rep a) p -> a Source #

Inverse of toData.

onData :: (UnifyRep r s, UnifyRep s r) => p (Data r x) (Data s y) -> p (Data r x) (Data s y) Source #

onData :: _ => (Data r x -> Data s y) -> (Data r x -> Data s y)  -- possible specialization

Can be used with generic-lens for type-changing field updates with field_ (and possibly other generic optics).

A specialization of the identity function to be used to fix types of functions on Data, unifying the "spines" of input and output generic representations (the "spine" is everything except field types, which may thus change).

Microsurgeries

Each microsurgery consists of a type family F to modify metadata in GHC Generic representations, and two mappings (that are just coerce):

  f :: Data (Rep a) p -> Data (F (Rep a)) p
unf :: Data (F (Rep a)) p -> Data (Rep a) p

Use f with toData for generic functions that consume generic values, and unf with fromData for generic functions that produce generic values. Abstract example:

genericSerialize . f . toData
fromData . unf . genericDeserialize

Renaming of fields and constructors

These surgeries require DataKinds and TypeApplications.

Examples

{-# LANGUAGE
    DataKinds,
    TypeApplications #-}

-- Rename all fields to "foo"
renameFields @(SConst "foo")

-- Rename constructor "Bar" to "Baz", and leave all others the same
renameConstrs @(SRename '[ '("Bar", "Baz") ] SId)

data RenameFields (rnm :: *) :: * Source #

Rename fields using the function rnm given as a parameter.

data Foo = Bar { baz :: Zap }

-- becomes, renaming "baz" to "bag" --

data Foo = Bar { bag :: Zap }

This is a defunctionalized symbol, applied using GSurgery or Surgery.

Instances

Instances details
type GSurgery (RenameFields rnm) (f :: k -> Type) Source # 
Instance details

Defined in Generic.Data.Internal.Microsurgery

type GSurgery (RenameFields rnm) (f :: k -> Type) = GRenameFields rnm f

renameFields :: forall rnm f p. Coercible (GSurgery (RenameFields rnm) f) f => Data f p -> Data (GSurgery (RenameFields rnm) f) p Source #

unrenameFields :: forall rnm f p. Coercible (GSurgery (RenameFields rnm) f) f => Data f p -> Data (GSurgery (RenameFields rnm) f) p Source #

data RenameConstrs (rnm :: *) :: * Source #

Rename constructors using the function rnm given as a parameter.

data Foo = Bar { baz :: Zap }

-- becomes, renaming "Bar" to "Car" --

data Foo = Car { baz :: Zap }

This is a defunctionalized symbol, applied using GSurgery or Surgery.

Instances

Instances details
type GSurgery (RenameConstrs rnm) (f :: k -> Type) Source # 
Instance details

Defined in Generic.Data.Internal.Microsurgery

type GSurgery (RenameConstrs rnm) (f :: k -> Type) = GRenameConstrs rnm f

renameConstrs :: forall rnm f p. Coercible (GSurgery (RenameConstrs rnm) f) f => Data f p -> Data (GSurgery (RenameConstrs rnm) f) p Source #

unrenameConstrs :: forall rnm f p. Coercible (GSurgery (RenameConstrs rnm) f) f => Data f p -> Data (GSurgery (RenameConstrs rnm) f) p Source #

Renaming functions

type family (f :: *) @@ (s :: Symbol) :: Symbol Source #

f @@ s is the application of a type-level function symbolized by f to a s :: Symbol.

A function FooToBar can be defined as follows:

data FooToBar
type instance FooToBar @@ "foo" = "bar"

Instances

Instances details
type SError @@ s Source # 
Instance details

Defined in Generic.Data.Internal.Microsurgery

type SError @@ s = TypeError ('Text "Invalid name: " :<>: 'ShowType s) :: Symbol
type SId @@ s Source # 
Instance details

Defined in Generic.Data.Internal.Microsurgery

type SId @@ s = s
type (SConst z) @@ _s Source # 
Instance details

Defined in Generic.Data.Internal.Microsurgery

type (SConst z) @@ _s = z
type (SRename xs f) @@ s Source # 
Instance details

Defined in Generic.Data.Internal.Microsurgery

type (SRename xs f) @@ s = SRename' xs f s

data SId Source #

Identity function Symbol -> Symbol.

Instances

Instances details
type SId @@ s Source # 
Instance details

Defined in Generic.Data.Internal.Microsurgery

type SId @@ s = s

data SError Source #

Empty function (compile-time error when applied).

Instances

Instances details
type SError @@ s Source # 
Instance details

Defined in Generic.Data.Internal.Microsurgery

type SError @@ s = TypeError ('Text "Invalid name: " :<>: 'ShowType s) :: Symbol

data SConst (s :: Symbol) Source #

Constant function.

Instances

Instances details
type (SConst z) @@ _s Source # 
Instance details

Defined in Generic.Data.Internal.Microsurgery

type (SConst z) @@ _s = z

data SRename (xs :: [(Symbol, Symbol)]) (f :: *) Source #

Define a function for a fixed set of strings, and fall back to f for the others.

Instances

Instances details
type (SRename xs f) @@ s Source # 
Instance details

Defined in Generic.Data.Internal.Microsurgery

type (SRename xs f) @@ s = SRename' xs f s

Wrap every field in a type constructor

Give every field a type f FieldType (where f is a parameter), to obtain a family of types with a shared structure. This "higher-kindification" technique is presented in the following blogposts:

See also the file test/one-liner-surgery.hs in this package for an example of using one-liner and generic-lens with a synthetic type constructed with DOnFields.

Example

Derive Semigroup and Monoid for a product of Num types:

{-# LANGUAGE DeriveGeneric, DerivingVia #-}
import Data.Monoid (Sum(..))  -- Constructors must be in scope
import GHC.Generics (Generic)
import Generic.Data.Microsurgery
  ( ProductSurgery
  , OnFields
  , GenericProduct(..)  -- Constructors must be in scope
  , Surgery'(..)        --
  )

data TwoCounters = MkTwoCounters { c1 :: Int, c2 :: Int }
  deriving Generic
  deriving (Semigroup, Monoid)
    via (ProductSurgery (OnFields Sum) TwoCounters)  -- Surgery here

data OnFields (f :: * -> *) :: * Source #

Apply a type constructor f to every field type of a generic representation r.

data Color = RGB
  { r :: Int
  , g :: Int
  , b :: Int }

-- becomes --

data Color f = RGB
  { r :: f Int
  , g :: f Int
  , b :: f Int }

This is a defunctionalized symbol, applied using GSurgery or Surgery.

Instances

Instances details
type GSurgery (OnFields f) (g :: k -> Type) Source # 
Instance details

Defined in Generic.Data.Internal.Microsurgery

type GSurgery (OnFields f) (g :: k -> Type) = GOnFields f g

type DOnFields (f :: * -> *) (a :: *) = Data (GSurgery (OnFields f) (Rep a)) () Source #

Apply a type constructor to every field type of a type a to make a synthetic type.

Substitute a generic representation from another type

Example

Derive Semigroup and Monoid for a product of Num types, but using Sum for one field and Product for the other. In other words, we use the fact that Polar a below is isomorphic to the monoid (Product a, Sum a).

{-# LANGUAGE DeriveGeneric, DerivingVia #-}
import Data.Monoid (Sum(..), Product(..))  -- Constructors must be in scope
import GHC.Generics (Generic)
import Generic.Data.Microsurgery
  ( ProductSurgery
  , CopyRep
  , GenericProduct(..)  -- Constructors must be in scope
  , Surgery'(..)        --
  )

data Polar a = Exp { modulus :: a, argument :: a }
  deriving Generic
  deriving (Semigroup, Monoid)
    via (ProductSurgery (CopyRep (Product a, Sum a)) (Polar a))  -- Surgery here

That is the polar representation of a complex number:

z = modulus * exp(i * argument)

The product of complex numbers defines a monoid isomorphic to the monoid product (Product Double, Sum Double) (multiply the moduli, add the arguments).

z1 <> z2
 = z1 * z2
 = Exp (modulus z1 * modulus z2) (argument z1 + argument z2)

mempty = 1 = Exp 1 0

data CopyRep (a :: *) :: * Source #

Change the generic representation to that of another type a.

Instances

Instances details
type GSurgery (CopyRep a) (_1 :: Type -> Type) Source # 
Instance details

Defined in Generic.Data.Internal.Microsurgery

type GSurgery (CopyRep a) (_1 :: Type -> Type) = Rep a

copyRep :: forall a f p. Coercible (GSurgery (CopyRep a) f) f => Data f p -> Data (GSurgery (CopyRep a) f) p Source #

uncopyRep :: forall a f p. Coercible f (GSurgery (CopyRep a) f) => Data (GSurgery (CopyRep a) f) p -> Data f p Source #

Type aging ("denewtypify")

data Typeage :: * Source #

Forget that a type is a newtype. (The pun is that "aging" a type makes it no longer "new".)

newtype Foo = Bar Baz

-- becomes --

data Foo = Bar Baz

This is a defunctionalized symbol, applied using GSurgery or Surgery.

Instances

Instances details
type GSurgery Typeage (M1 D ('MetaData nm md pk _nt) f :: k -> Type) Source # 
Instance details

Defined in Generic.Data.Internal.Microsurgery

type GSurgery Typeage (M1 D ('MetaData nm md pk _nt) f :: k -> Type) = M1 D ('MetaData nm md pk 'False) f

Derecordify

data Derecordify :: * Source #

Forget that a type was declared using record syntax.

data Foo = Bar { baz :: Zap }

-- becomes --

data Foo = Bar Zap

Concretely, set the last field of MetaCons to False and forget field names.

This is a defunctionalized symbol, applied using GSurgery or Surgery.

Instances

Instances details
type GSurgery Derecordify (f :: k -> Type) Source # 
Instance details

Defined in Generic.Data.Internal.Microsurgery

type GSurgery Derecordify (f :: k -> Type) = GDerecordify f