-- | Surgery for generic data types:
-- remove and insert constructors and fields.
--
-- Functions in this module are expected to be used with visible type
-- applications. Surgeries have a lot of type parameters, but usually only the
-- first one to three type arguments need to be passed via @TypeApplications@.
-- Functions are annotated with \"functional dependencies\", with a meaning
-- similar to the homonymous GHC extension for type classes (click on
-- \"Details\" under each function to see those).
--
-- Remember that not all parameters to the left of a functional dependency
-- arrow need to be annotated explicitly to determine those on the right. Some
-- can also be inferred from the context.
--
-- Note that constructors and fields are indexed from zero.
module Generic.Data.Surgery
( Data
, toData
, fromData
, onData
-- Microsurgery
-- One common and simple situation is to wrap a couple of fields in some
-- newtype. You can leverage the @generic-lens@ library with the three
-- functions below.
--
-- @
-- over :: ASetter s t a b -> (a -> b) -> s -> t -- from lens or microlens
-- field :: HasField s t a b => Lens s t a b -- from generic-lens
-- @
--
-- For example, to wrap a field named @hidden@ in a newtype like
-- 'Generic.Data.Opaque' in some record type @R@:
--
-- @
-- 'onData' (over (field @"hidden") 'Generic.Data.Opaque') . 'toData'
-- :: R -> Data _ _
-- @
--
-- The result is a type, that from the point of view of "GHC.Generics"
-- looks just like @R@ but with the field @hidden@ wrapped.
-- * Getting into the operating room
, OR
, toOR
, fromOR'
, toOR'
, fromOR
, OROf
-- * Surgeries
-- ** Unnamed fields
, removeCField
, insertCField
, insertCField'
, modifyCField
-- ** Named fields (records)
, removeRField
, insertRField
, insertRField'
, modifyRField
-- ** Constructors
-- | A constructor is extracted to a "tuple", which can be any
-- 'GHC.Generics.Generic' single-constructor type with the same number of
-- fields.
--
-- Note that @()@ and 'Data.Functor.Identity.Identity' can be used as an
-- empty and a singleton tuple type respectively.
--
-- When the tuple type can't be inferred and doesn't really matter,
-- an alternative to explicit type annotations is to use the @...ConstrT@
-- variants of these surgeries, which are specialized to actual tuples
-- (@()@, 'Data.Functor.Identity.Identity', @(,)@, @(,,)@, up to 7 ---
-- because that's where 'GHC.Generics.Generic' instances currently stop).
, removeConstr
, insertConstr
, modifyConstr
, removeConstrT
, insertConstrT
, modifyConstrT
-- * Constraint synonyms
-- | Hiding implementation details from the signatures above.
-- Useful to compose surgeries in a reusable way.
-- ** Conversions
, ToORRep
, ToOR
, FromORRep
, FromOR
-- ** Surgeries
, RmvCField
, InsCField
, ModCField
, RmvRField
, InsRField
, ModRField
, RmvConstr
, InsConstr
, ModConstr
, RmvConstrT
, InsConstrT
, ModConstrT
) where
import Generic.Data.Internal.Data
import Generic.Data.Surgery.Internal