{-# LANGUAGE
AllowAmbiguousTypes,
DataKinds,
FlexibleContexts,
FlexibleInstances,
MultiParamTypeClasses,
PolyKinds,
ScopedTypeVariables,
TypeFamilies,
TypeOperators,
UndecidableInstances #-}
module Generic.Data.Internal.Microsurgery where
import Data.Coerce (Coercible, coerce)
import GHC.Generics
import GHC.TypeLits (ErrorMessage(..), Symbol, TypeError)
import Generic.Data.Types (Data)
import Generic.Data.Internal.Generically (Generically(..), GenericProduct(..))
type Surgery (s :: *) (a :: *) = Generically (Surgery' s a)
type ProductSurgery (s :: *) (a :: *) = GenericProduct (Surgery' s a)
newtype Surgery' (s :: *) (a :: *) = Surgery' { unSurgery' :: a }
instance (Generic a, Coercible (GSurgery s (Rep a)) (Rep a)) => Generic (Surgery' s a) where
type Rep (Surgery' s a) = GSurgery s (Rep a)
from = (coerce :: forall x. (a -> Rep a x) -> Surgery' s a -> GSurgery s (Rep a) x) from
to = (coerce :: forall x. (Rep a x -> a) -> GSurgery s (Rep a) x -> Surgery' s a) to
type family GSurgery (s :: *) (f :: k -> *) :: k -> *
derecordify ::
Coercible (GSurgery Derecordify f) f =>
Data f p -> Data (GSurgery Derecordify f) p
derecordify = coerce
underecordify ::
Coercible f (GSurgery Derecordify f) =>
Data (GSurgery Derecordify f) p -> Data f p
underecordify = coerce
data Derecordify :: *
type instance GSurgery Derecordify f = GDerecordify f
type family GDerecordify (f :: k -> *) :: k -> *
type instance GDerecordify (M1 D m f) = M1 D m (GDerecordify f)
type instance GDerecordify (f :+: g) = GDerecordify f :+: GDerecordify g
type instance GDerecordify (f :*: g) = GDerecordify f :*: GDerecordify g
type instance GDerecordify (M1 C ('MetaCons nm fx _isRecord) f) = M1 C ('MetaCons nm fx 'False) (GDerecordify f)
type instance GDerecordify (M1 S ('MetaSel _nm su ss ds) f) = M1 S ('MetaSel 'Nothing su ss ds) f
type instance GDerecordify V1 = V1
type instance GDerecordify U1 = U1
typeage ::
Coercible (GSurgery Typeage f) f =>
Data f p -> Data (GSurgery Typeage f) p
typeage = coerce
untypeage ::
Coercible f (GSurgery Typeage f) =>
Data (GSurgery Typeage f) p -> Data f p
untypeage = coerce
data Typeage :: *
type instance GSurgery Typeage (M1 D ('MetaData nm md pk _nt) f) = M1 D ('MetaData nm md pk 'False) f
renameFields ::
forall rnm f p.
Coercible (GSurgery (RenameFields rnm) f) f =>
Data f p -> Data (GSurgery (RenameFields rnm) f) p
renameFields = coerce
unrenameFields ::
forall rnm f p.
Coercible (GSurgery (RenameFields rnm) f) f =>
Data f p -> Data (GSurgery (RenameFields rnm) f) p
unrenameFields = coerce
renameConstrs ::
forall rnm f p.
Coercible (GSurgery (RenameConstrs rnm) f) f =>
Data f p -> Data (GSurgery (RenameConstrs rnm) f) p
renameConstrs = coerce
unrenameConstrs ::
forall rnm f p.
Coercible (GSurgery (RenameConstrs rnm) f) f =>
Data f p -> Data (GSurgery (RenameConstrs rnm) f) p
unrenameConstrs = coerce
data RenameFields (rnm :: *) :: *
type instance GSurgery (RenameFields rnm) f = GRenameFields rnm f
type family GRenameFields (rnm :: *) (f :: k -> *) :: k -> *
type instance GRenameFields rnm (M1 D m f) = M1 D m (GRenameFields rnm f)
type instance GRenameFields rnm (f :+: g) = GRenameFields rnm f :+: GRenameFields rnm g
type instance GRenameFields rnm (f :*: g) = GRenameFields rnm f :*: GRenameFields rnm g
type instance GRenameFields rnm (M1 C m f) = M1 C m (GRenameFields rnm f)
type instance GRenameFields rnm (M1 S ('MetaSel ('Just nm) su ss ds) f) = M1 S ('MetaSel ('Just (rnm @@ nm)) su ss ds) f
type instance GRenameFields rnm V1 = V1
type instance GRenameFields rnm U1 = U1
data RenameConstrs (rnm :: *) :: *
type instance GSurgery (RenameConstrs rnm) f = GRenameConstrs rnm f
type family GRenameConstrs (rnm :: *) (f :: k -> *) :: k -> *
type instance GRenameConstrs rnm (M1 D m f) = M1 D m (GRenameConstrs rnm f)
type instance GRenameConstrs rnm (f :+: g) = GRenameConstrs rnm f :+: GRenameConstrs rnm g
type instance GRenameConstrs rnm (f :*: g) = GRenameConstrs rnm f :*: GRenameConstrs rnm g
type instance GRenameConstrs rnm (M1 C ('MetaCons nm fi ir) f) = M1 C ('MetaCons (rnm @@ nm) fi ir) f
type instance GRenameConstrs rnm V1 = V1
type family (f :: *) @@ (s :: Symbol) :: Symbol
data SId
type instance SId @@ s = s
data SError
type instance SError @@ s = TypeError ('Text "Invalid name: " ':<>: 'ShowType s)
data SConst (s :: Symbol)
type instance SConst z @@ _s = z
data SRename (xs :: [(Symbol, Symbol)]) (f :: *)
type instance SRename xs f @@ s = SRename' xs f s
type family SRename' (xs :: [(Symbol, Symbol)]) (f :: *) (s :: Symbol) where
SRename' '[] f s = f @@ s
SRename' ('( s, t) ': _xs) _f s = t
SRename' ('(_r, _t) ': xs) f s = SRename' xs f s
class UnifyRep (f :: k -> *) (g :: k -> *)
instance (g' ~ M1 s c g, UnifyRep f g) => UnifyRep (M1 s c f) g'
instance (g' ~ (g1 :+: g2), UnifyRep f1 g1, UnifyRep f2 g2)
=> UnifyRep (f1 :+: f2) g'
instance (g' ~ (g1 :*: g2), UnifyRep f1 g1, UnifyRep f2 g2)
=> UnifyRep (f1 :*: f2) g'
instance (g' ~ K1 i b) => UnifyRep (K1 i a) g'
instance (g' ~ U1) => UnifyRep U1 g'
instance (g' ~ V1) => UnifyRep V1 g'
onData
:: (UnifyRep r s, UnifyRep s r)
=> p (Data r x) (Data s y) -> p (Data r x) (Data s y)
onData = id
data OnFields (f :: * -> *) :: *
type instance GSurgery (OnFields f) g = GOnFields f g
type family GOnFields (f :: * -> *) (g :: k -> *) :: k -> *
type instance GOnFields f (M1 s m r) = M1 s m (GOnFields f r)
type instance GOnFields f (r :+: s) = GOnFields f r :+: GOnFields f s
type instance GOnFields f (r :*: s) = GOnFields f r :*: GOnFields f s
type instance GOnFields f (K1 i a) = K1 i (f a)
type instance GOnFields f U1 = U1
type instance GOnFields f V1 = V1
type DOnFields (f :: * -> *) (a :: *) = Data (GSurgery (OnFields f) (Rep a)) ()
data CopyRep (a :: *) :: *
type instance GSurgery (CopyRep a) _ = Rep a
copyRep :: forall a f p.
Coercible (GSurgery (CopyRep a) f) f =>
Data f p -> Data (GSurgery (CopyRep a) f) p
copyRep = coerce
uncopyRep :: forall a f p.
Coercible f (GSurgery (CopyRep a) f) =>
Data (GSurgery (CopyRep a) f) p -> Data f p
uncopyRep = coerce