{-# LANGUAGE
AllowAmbiguousTypes,
BangPatterns,
ConstraintKinds,
DataKinds,
DeriveGeneric,
FlexibleContexts,
FlexibleInstances,
LambdaCase,
MultiParamTypeClasses,
PolyKinds,
ScopedTypeVariables,
TypeApplications,
TypeFamilies,
TypeOperators,
TypeInType,
UndecidableInstances,
UndecidableSuperClasses #-}
module Generic.Data.Surgery.Internal where
import Control.Monad ((<=<))
import Data.Bifunctor (first, second)
import Data.Coerce
import Data.Functor.Identity (Identity)
import Data.Kind (Constraint, Type)
import Data.Type.Equality (type (==))
import GHC.Generics
import GHC.TypeLits
import Fcf
( Exp, Eval, If, Pure, Pure2, Bimap, Uncurry
, type (@@), type (=<<), type (<=<), type (<$>)
)
import Generic.Data (MetaOf, MetaConsName)
import Generic.Data.Internal.Compat (Div)
import Generic.Data.Internal.Data (Data(Data,unData))
import Generic.Data.Internal.Meta (UnM1)
import Generic.Data.Internal.Utils (coerce', absurd1)
newtype OR (l :: k -> Type) (x :: k) = OR { unOR :: l x }
toOR :: forall a l x. (Generic a, ToORRep a l) => a -> OR l x
toOR = OR . gLinearize . from
toORLazy :: forall a l x. (Generic a, ToORRepLazy a l) => a -> OR l x
toORLazy = OR . gLinearize @(Arborify l) . coerce' . from
fromOR' :: forall f l x. FromOR f l => OR l x -> Data f x
fromOR' = Data . gArborify . unOR
toOR' :: forall f l x. ToOR f l => Data f x -> OR l x
toOR' = OR . gLinearize . unData
fromOR :: forall a l x. (Generic a, FromORRep a l) => OR l x -> a
fromOR = to . gArborify . unOR
fromORLazy :: forall a l x. (Generic a, FromORRepLazy a l) => OR l x -> a
fromORLazy = to . coerce' . gArborify @(Lazify (Rep a)) . unOR
type OROf a = OR (Linearize (Rep a)) ()
type OROfLazy a = OR (Linearize (Lazify (Rep a))) ()
type ToORRep a l = ToOR (Rep a) l
type FromORRep a l = FromOR (Rep a) l
type ToOR f l = (GLinearize f, Linearize f ~ l, f ~ Arborify l)
type FromOR f l = (GArborify f, Linearize f ~ l, f ~ Arborify l)
type ToORRepLazy a l = ToORLazy (Rep a) l
type FromORRepLazy a l = FromORLazy (Rep a) l
type FromORLazy f l = (FromOR (Lazify f) l, Coercible (Arborify l) f)
type ToORLazy f l = (ToOR (Lazify f) l, Coercible f (Arborify l))
removeCField
:: forall n t lt l x
. RmvCField n t lt l
=> OR lt x -> (t, OR l x)
removeCField (OR a) = OR <$> gRemoveField @n a
removeRField
:: forall fd n t lt l x
. RmvRField fd n t lt l
=> OR lt x -> (t, OR l x)
removeRField (OR a) = OR <$> gRemoveField @n a
insertCField
:: forall n t lt l x
. InsCField n t lt l
=> (t, OR l x) -> OR lt x
insertCField = uncurry (insertCField' @n)
insertCField'
:: forall n t lt l x
. InsCField n t lt l
=> t -> OR l x -> OR lt x
insertCField' z (OR a) = OR (gInsertField @n z a)
insertRField
:: forall fd n t lt l x
. InsRField fd n t lt l
=> (t, OR l x) -> OR lt x
insertRField = uncurry (insertRField' @fd)
insertRField'
:: forall fd n t lt l x
. InsRField fd n t lt l
=> t -> OR l x -> OR lt x
insertRField' z (OR a) = OR (gInsertField @n z a)
modifyCField
:: forall n t t' lt lt' l x
. ModCField n t t' lt lt' l
=> (t -> t') -> OR lt x -> OR lt' x
modifyCField f = insertCField @n @t' . first f . removeCField @n @t
modifyRField
:: forall fd n t t' lt lt' l x
. ModRField fd n t t' lt lt' l
=> (t -> t') -> OR lt x -> OR lt' x
modifyRField f = insertRField @fd @n @t' . first f . removeRField @fd @n @t
removeConstr
:: forall c n t lc l x
. RmvConstr c n t lc l
=> OR lc x -> Either t (OR l x)
removeConstr (OR a) = second OR (gRemoveConstr @n a)
removeConstrT
:: forall c n t lc l x
. RmvConstrT c n t lc l
=> OR lc x -> Either t (OR l x)
removeConstrT = removeConstr @c @n @t
insertConstr
:: forall c n t lc l x
. InsConstr c n t lc l
=> Either t (OR l x) -> OR lc x
insertConstr z = OR (gInsertConstr @n (second unOR z))
insertConstrT
:: forall c n t lc l x
. InsConstrT c n t lc l
=> Either t (OR l x) -> OR lc x
insertConstrT = insertConstr @c @n @t
modifyConstr
:: forall c n t t' lc lc' l x
. ModConstr c n t t' lc lc' l
=> (t -> t') -> OR lc x -> OR lc' x
modifyConstr f = insertConstr @c @n @t' . first f . removeConstr @c @n @t
modifyConstrT
:: forall c n t t' lc lc' l x
. ModConstrT c n t t' lc lc' l
=> (t -> t') -> OR lc x -> OR lc' x
modifyConstrT = modifyConstr @c @n @t @t'
type RmvCField n t lt l =
( GRemoveField n t lt l
, CFieldSurgery n t lt l
)
type RmvRField fd n t lt l =
( GRemoveField n t lt l
, RFieldSurgery fd n t lt l
)
type InsCField n t lt l =
( GInsertField n t l lt
, CFieldSurgery n t lt l
)
type InsRField fd n t lt l =
( GInsertField n t l lt
, RFieldSurgery fd n t lt l
)
type ModCField n t t' lt lt' l =
( RmvCField n t lt l
, InsCField n t' lt' l
)
type ModRField fd n t t' lt lt' l =
( RmvRField fd n t lt l
, InsRField fd n t' lt' l
)
type RmvConstr c n t lc l =
( GRemoveConstr n t lc l
, ConstrSurgery c n t lc l (Eval (ConstrAt n lc))
)
type RmvConstrT c n t lc l =
( RmvConstr c n t lc l
, IsTuple (Arity (Eval (ConstrAt n lc))) t
)
type InsConstr c n (t :: Type) lc l =
( GInsertConstr n t l lc
, ConstrSurgery c n t lc l (Eval (ConstrAt n lc))
)
type InsConstrT c n t lc l =
( InsConstr c n t lc l
, IsTuple (Arity (Eval (ConstrAt n lc))) t
)
type ModConstr c n t t' lc lc' l =
( RmvConstr c n t lc l
, InsConstr c n t' lc' l
)
type ModConstrT c n t t' lc lc' l =
( ModConstr c n t t' lc lc' l
, IsTuple (Arity (Eval (ConstrAt n lc ))) t
, IsTuple (Arity (Eval (ConstrAt n lc'))) t'
)
type FieldSurgery n t lt l =
( t ~ Eval (FieldTypeAt n lt)
, l ~ Eval (RemoveField n t lt)
)
type CFieldSurgery n t lt l =
( lt ~ Eval (InsertField n 'Nothing t l)
, FieldSurgery n t lt l
)
type RFieldSurgery fd n t lt l =
( n ~ Eval (FieldIndex fd lt)
, lt ~ Eval (InsertField n ('Just fd) t l)
, FieldSurgery n t lt l
)
type ConstrSurgery c n t lc l l_t =
( Generic t
, MatchFields (Linearize (UnM1 (Rep t))) l_t
, n ~ Eval (ConstrIndex c lc)
, c ~ MetaConsName (MetaOf l_t)
, lc ~ Eval (InsertUConstrAtL n l_t l)
, l ~ Eval (RemoveUConstrAt_ n lc)
)
type family Linearize (f :: k -> Type) :: k -> Type
type instance Linearize (M1 D m f) = M1 D m (LinearizeSum f V1)
type instance Linearize (M1 C m f) = M1 C m (LinearizeProduct f U1)
type family LinearizeSum (f :: k -> Type) (tl :: k -> Type) :: k -> Type
type instance LinearizeSum V1 tl = tl
type instance LinearizeSum (f :+: g) tl = LinearizeSum f (LinearizeSum g tl)
type instance LinearizeSum (M1 c m f) tl = M1 c m (LinearizeProduct f U1) :+: tl
type family LinearizeProduct (f :: k -> Type) (tl :: k -> Type) :: k -> Type
type instance LinearizeProduct U1 tl = tl
type instance LinearizeProduct (f :*: g) tl = LinearizeProduct f (LinearizeProduct g tl)
type instance LinearizeProduct (M1 s m f) tl = M1 s m f :*: tl
class GLinearize f where
gLinearize :: f x -> Linearize f x
instance GLinearizeSum f V1 => GLinearize (M1 D m f) where
gLinearize (M1 a) = M1 (gLinearizeSum @_ @V1 (Left a))
instance GLinearizeProduct f U1 => GLinearize (M1 C m f) where
gLinearize (M1 a) = M1 (gLinearizeProduct a U1)
class GLinearizeSum f tl where
gLinearizeSum :: Either (f x) (tl x) -> LinearizeSum f tl x
instance GLinearizeSum V1 tl where
gLinearizeSum (Left v) = absurd1 v
gLinearizeSum (Right c) = c
instance (GLinearizeSum g tl, GLinearizeSum f (LinearizeSum g tl))
=> GLinearizeSum (f :+: g) tl where
gLinearizeSum (Left (L1 a)) = gLinearizeSum @_ @(LinearizeSum g tl) (Left a)
gLinearizeSum (Left (R1 b)) = gLinearizeSum @f (Right (gLinearizeSum @g @tl (Left b)))
gLinearizeSum (Right c) = gLinearizeSum @f (Right (gLinearizeSum @g (Right c)))
instance GLinearizeProduct f U1 => GLinearizeSum (M1 c m f) tl where
gLinearizeSum (Left (M1 a)) = L1 (M1 (gLinearizeProduct a U1))
gLinearizeSum (Right c) = R1 c
class GLinearizeProduct f tl where
gLinearizeProduct :: f x -> tl x -> LinearizeProduct f tl x
instance GLinearizeProduct U1 tl where
gLinearizeProduct _ = id
instance (GLinearizeProduct g tl, GLinearizeProduct f (LinearizeProduct g tl))
=> GLinearizeProduct (f :*: g) tl where
gLinearizeProduct (a :*: b) = gLinearizeProduct a . gLinearizeProduct b
instance GLinearizeProduct (M1 s m f) tl where
gLinearizeProduct = (:*:)
class GArborify f where
gArborify :: Linearize f x -> f x
instance GArborifySum f V1 => GArborify (M1 D m f) where
gArborify (M1 a) = case gArborifySum @_ @V1 a of
Left a' -> M1 a'
Right v -> absurd1 v
instance GArborifyProduct f U1 => GArborify (M1 C m f) where
gArborify (M1 a) = M1 (fst (gArborifyProduct @_ @U1 a))
class GArborifySum f tl where
gArborifySum :: LinearizeSum f tl x -> Either (f x) (tl x)
instance GArborifySum V1 tl where
gArborifySum = Right
instance (GArborifySum g tl, GArborifySum f (LinearizeSum g tl))
=> GArborifySum (f :+: g) tl where
gArborifySum = first R1 . gArborifySum <=< first L1 . gArborifySum
instance GArborifyProduct f U1 => GArborifySum (M1 c m f) tl where
gArborifySum (L1 (M1 a)) = Left (M1 (fst (gArborifyProduct @_ @U1 a)))
gArborifySum (R1 c) = Right c
class GArborifyProduct f tl where
gArborifyProduct :: LinearizeProduct f tl x -> (f x, tl x)
instance GArborifyProduct U1 tl where
gArborifyProduct c = (U1, c)
instance (GArborifyProduct g tl, GArborifyProduct f (LinearizeProduct g tl))
=> GArborifyProduct (f :*: g) tl where
gArborifyProduct abc = (a :*: b, c) where
(a, bc) = gArborifyProduct abc
(b, c) = gArborifyProduct bc
instance GArborifyProduct (M1 s m f) tl where
gArborifyProduct (a :*: c) = (a, c)
type family Arborify (f :: k -> Type) :: k -> Type
type instance Arborify (M1 D m f) = M1 D m (Eval (ArborifySum (CoArity f) f))
type instance Arborify (M1 C m f) = M1 C m (Eval (ArborifyProduct (Arity f) f))
data ArborifySum (n :: Nat) (f :: k -> Type) :: Exp (k -> Type)
type instance Eval (ArborifySum n V1) = V1
type instance Eval (ArborifySum n (f :+: g)) =
Eval (If (n == 1)
(ArborifyProduct (Arity f) f)
(Arborify' ArborifySum (:+:) n (Div n 2) f g))
data ArborifyProduct (n :: Nat) (f :: k -> Type) :: Exp (k -> Type)
type instance Eval (ArborifyProduct n (M1 C s f)) = M1 C s (Eval (ArborifyProduct n f))
type instance Eval (ArborifyProduct n U1) = U1
type instance Eval (ArborifyProduct n (f :*: g)) =
Eval (If (n == 1)
(Pure f)
(Arborify' ArborifyProduct (:*:) n (Div n 2) f g))
type Arborify' arb op n nDiv2 f g =
( Uncurry (Pure2 op)
<=< Bimap (arb nDiv2) (arb (n-nDiv2))
<=< SplitAt nDiv2
) (op f g)
type family Lazify (f :: k -> Type) :: k -> Type
type instance Lazify (M1 i m f) = M1 i (LazifyMeta m) (Lazify f)
type instance Lazify (f :*: g) = Lazify f :*: Lazify g
type instance Lazify (f :+: g) = Lazify f :+: Lazify g
type instance Lazify (K1 i c) = K1 i c
type instance Lazify U1 = U1
type instance Lazify V1 = V1
type family LazifyMeta (m :: Meta) :: Meta
type instance LazifyMeta ('MetaData n m p nt) = 'MetaData n m p nt
type instance LazifyMeta ('MetaCons n f s) = 'MetaCons n f s
type instance LazifyMeta ('MetaSel mn su ss ds)
= 'MetaSel mn 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy
data SplitAt :: Nat -> (k -> Type) -> Exp (k -> Type, k -> Type)
type instance Eval (SplitAt n (f :+: g)) =
Eval (If (n == 0)
(Pure '(V1, f :+: g))
(Bimap (Pure2 (:+:) f) Pure =<< SplitAt (n-1) g))
type instance Eval (SplitAt n (f :*: g)) =
Eval (If (n == 0)
(Pure '(U1, f :*: g))
(Bimap (Pure2 (:*:) f) Pure =<< SplitAt (n-1) g))
type MajorSurgery k = MajorSurgery_ k
type Operate (f :: k -> Type) (s :: MajorSurgery k) = Operate_ f s
type MajorSurgery_ k = (k -> Type) -> Exp (k -> Type)
type Operate_ (f :: k -> Type) (s :: MajorSurgery k) = Arborify (OperateL (Linearize f) s)
type OperateL (l :: k -> Type) (s :: MajorSurgery k) = Eval (s l)
data (:>>) :: MajorSurgery k -> MajorSurgery k -> MajorSurgery k
type instance Eval ((s :>> t) l) = Eval (t (Eval (s l)))
type instance PerformL l (s :>> t) = (PerformL l s, PerformL (Eval (s l)) t)
infixl 1 :>>
data IdSurgery :: MajorSurgery k
type instance Eval (IdSurgery l) = l
type instance PerformL l IdSurgery = ()
data Suture :: MajorSurgery k
type instance Eval (Suture l) = Linearize (Arborify l)
type family PerformL (l :: k -> Type) (s :: MajorSurgery k) :: Constraint
class Perform_ r s => Perform (r :: k -> Type) (s :: MajorSurgery k)
instance Perform_ r s => Perform (r :: k -> Type) (s :: MajorSurgery k)
type Perform_ (r :: k -> Type) (s :: MajorSurgery k) =
( PerformL (Linearize r) s
, ToOR r (Linearize r)
, FromOR (Operate r s) (OperateL (Linearize r) s)
)
data FieldTypeAt (n :: Nat) (f :: k -> Type) :: Exp Type
type instance Eval (FieldTypeAt n (M1 i c f)) = Eval (FieldTypeAt n f)
type instance Eval (FieldTypeAt n (f :+: V1)) = Eval (FieldTypeAt n f)
type instance Eval (FieldTypeAt n (f :*: g)) =
Eval (If (n == 0) (Pure (FieldTypeOf f)) (FieldTypeAt (n-1) g))
type family FieldTypeOf (f :: k -> Type) :: Type
type instance FieldTypeOf (M1 s m (K1 i a)) = a
data FieldNameAt (n :: Nat) (f :: k -> Type) :: Exp (Maybe Symbol)
type instance Eval (FieldNameAt n (M1 i c f)) = Eval (FieldNameAt n f)
type instance Eval (FieldNameAt n (f :+: V1)) = Eval (FieldNameAt n f)
type instance Eval (FieldNameAt n (f :*: g)) =
Eval (If (n == 0) (FieldNameOf f) (FieldNameAt (n-1) g))
data FieldNameOf (f :: k -> Type) :: Exp (Maybe Symbol)
type instance Eval (FieldNameOf (M1 S ('MetaSel mn _ _ _) _)) = mn
data RemoveField (n :: Nat) (a :: Type) :: MajorSurgery k
type instance Eval (RemoveField n a f) = Eval (RemoveField_ n f)
data RemoveField_ (n :: Nat) :: MajorSurgery k
type instance Eval (RemoveField_ n (M1 i m f)) = M1 i m (Eval (RemoveField_ n f))
type instance Eval (RemoveField_ n (f :+: V1)) = Eval (RemoveField_ n f) :+: V1
type instance Eval (RemoveField_ n (f :*: g)) =
Eval (If (n == 0) (Pure g) ((:*:) f <$> RemoveField_ (n-1) g))
type instance PerformL lt (RemoveField n a) = PerformL lt (RemoveFieldAt n (FieldNameAt n @@ lt) a)
data RemoveFieldAt (n :: Nat) (fd :: Maybe Symbol) (a :: Type) :: MajorSurgery k
type instance PerformL lt (RemoveFieldAt n fd a) =
PerformLRemoveFieldAt n fd a lt (Eval (RemoveField_ n lt))
type PerformLRemoveFieldAt_ n fd t lt l =
( GRemoveField n t lt l
, t ~ Eval (FieldTypeAt n lt)
, lt ~ Eval (InsertField n fd t l)
)
class PerformLRemoveFieldAt_ n fd t lt l => PerformLRemoveFieldAt n fd t lt l
instance PerformLRemoveFieldAt_ n fd t lt l => PerformLRemoveFieldAt n fd t lt l
data RemoveRField (fd :: Symbol) (a :: Type) :: MajorSurgery k
type instance Eval (RemoveRField fd a f) = Eval (RemoveField_ (Eval (FieldIndex fd f)) f)
type instance PerformL lt (RemoveRField fd a) =
PerformL lt (RemoveFieldAt (FieldIndex fd @@ lt) ('Just fd) a)
type DefaultMetaSel field
= 'MetaSel field 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy
data InsertField (n :: Nat) (fd :: Maybe Symbol) (t :: Type) :: MajorSurgery k
type instance Eval (InsertField n fd t (M1 D m f)) = M1 D m (Eval (InsertField n fd t f))
type instance Eval (InsertField n fd t (M1 C m f)) = M1 C m (Eval (InsertField n fd t f))
type instance Eval (InsertField n fd t (f :+: V1)) = Eval (InsertField n fd t f) :+: V1
type instance Eval (InsertField n fd t (f :*: g)) =
Eval (If (n == 0)
(Pure (M1 S (DefaultMetaSel fd) (K1 R t) :*: (f :*: g)))
((:*:) f <$> InsertField (n-1) fd t g))
type instance Eval (InsertField 0 fd t U1) = M1 S (DefaultMetaSel fd) (K1 R t) :*: U1
type instance PerformL l (InsertField n fd t) = PerformLInsert n fd t l (Eval (InsertField n fd t l))
type PerformLInsert_ n fd t l tl =
( GInsertField n t l tl
, l ~ Eval (RemoveField_ n tl)
, tl ~ Eval (InsertField n fd t l)
, CheckField n fd tl
, t ~ Eval (FieldTypeAt n tl)
)
class PerformLInsert_ n fd t l tl => PerformLInsert n fd t l tl
instance PerformLInsert_ n fd t l tl => PerformLInsert n fd t l tl
type family CheckField (n :: Nat) (fd :: Maybe Symbol) (tl :: k -> Type) :: Constraint where
CheckField n 'Nothing tl = ()
CheckField n ('Just fd) tl = (n ~ Eval (FieldIndex fd tl))
data Succ :: Nat -> Exp Nat
type instance Eval (Succ n) = 1 + n
data FieldIndex (field :: Symbol) (f :: k -> Type) :: Exp Nat
type instance Eval (FieldIndex field (M1 D m f)) = Eval (FieldIndex field f)
type instance Eval (FieldIndex field (M1 C m f)) = Eval (FieldIndex field f)
type instance Eval (FieldIndex field (f :+: V1)) = Eval (FieldIndex field f)
type instance Eval (FieldIndex field (M1 S ('MetaSel ('Just field') su ss ds) f :*: g))
= Eval (If (field == field') (Pure 0) (Succ =<< FieldIndex field g))
type family Arity (f :: k -> Type) :: Nat
type instance Arity (M1 d m f) = Arity f
type instance Arity (f :+: V1) = Arity f
type instance Arity (f :*: g) = Arity f + Arity g
type instance Arity (K1 i c) = 1
type instance Arity U1 = 0
type family CoArity (f :: k -> Type) :: Nat
type instance CoArity (M1 D m f) = CoArity f
type instance CoArity (M1 C m f) = 1
type instance CoArity V1 = 0
type instance CoArity (f :+: g) = CoArity f + CoArity g
class GRemoveField (n :: Nat) a f g where
gRemoveField :: f x -> (a, g x)
instance GRemoveField n a f g => GRemoveField n a (M1 i c f) (M1 i c g) where
gRemoveField (M1 a) = M1 <$> gRemoveField @n a
instance GRemoveField n a f g => GRemoveField n a (f :+: V1) (g :+: V1) where
gRemoveField (L1 a) = L1 <$> gRemoveField @n a
gRemoveField (R1 v) = absurd1 v
instance GRemoveField 0 a (M1 s m (K1 i a) :*: f) f where
gRemoveField (M1 (K1 t) :*: b) = (t, b)
instance {-# OVERLAPPABLE #-}
( (n == 0) ~ 'False
, f0g ~ (f0 :*: g)
, GRemoveField (n-1) a f g
) => GRemoveField n a (f0 :*: f) f0g where
gRemoveField (a :*: b) = (a :*:) <$> gRemoveField @(n-1) b
class GInsertField (n :: Nat) a f g where
gInsertField :: a -> f x -> g x
instance GInsertField n a f g => GInsertField n a (M1 i c f) (M1 i c g) where
gInsertField t (M1 a) = M1 (gInsertField @n t a)
instance GInsertField n a f g => GInsertField n a (f :+: V1) (g :+: V1) where
gInsertField t (L1 a) = L1 (gInsertField @n t a)
gInsertField _ (R1 v) = absurd1 v
instance GInsertField 0 a f (M1 s m (K1 i a) :*: f) where
gInsertField t ab = M1 (K1 t) :*: ab
instance {-# OVERLAPPABLE #-}
( (n == 0) ~ 'False
, f0f ~ (f0 :*: f)
, GInsertField (n-1) a f g
) => GInsertField n a f0f (f0 :*: g) where
gInsertField t (a :*: b) = a :*: gInsertField @(n-1) t b
data ConstrAt (n :: Nat) (f :: k -> Type) :: Exp (k -> Type)
type instance Eval (ConstrAt n (M1 i m f)) = Eval (ConstrAt n f)
type instance Eval (ConstrAt n (f :+: g)) =
Eval (If (n == 0) (Pure f) (ConstrAt (n-1) g))
data RemoveConstr (c :: Symbol) (t :: Type) :: MajorSurgery k
type instance Eval (RemoveConstr c t l) = Eval (RemoveConstrAt c (ConstrIndex c @@ l) t l)
type instance PerformL lc (RemoveConstr c t) = PerformLRemoveConstr lc c (ConstrIndex c @@ lc) t
type PerformLRemoveConstr lc c n (t :: Type) =
PerformLRemoveConstrAt c n t (Eval (ConstrAt n lc)) lc (Eval (RemoveUConstrAt_ n lc))
type PerformLRemoveConstrAt_ c n t l_t lc l =
( GRemoveConstr n t lc l
, c ~ MetaConsName (MetaOf l_t)
, lc ~ Eval (InsertUConstrAtL n l_t l)
, MatchFields (Linearize (UnM1 (Rep t))) l_t
, Arity l_t ~ Arity (Linearize (UnM1 (Rep t)))
)
class PerformLRemoveConstrAt_ c n t l_t lc l => PerformLRemoveConstrAt c n (t :: Type) l_t lc l
instance PerformLRemoveConstrAt_ c n t l_t lc l => PerformLRemoveConstrAt c n (t :: Type) l_t lc l
data RemoveConstrAt (c :: Symbol) (n :: Nat) (t :: Type) :: MajorSurgery k
type instance Eval (RemoveConstrAt _ n t l) = Eval (RemoveUConstrAt n t l)
data RemoveUConstrAt (n :: Nat) (t :: Type) :: MajorSurgery k
type instance Eval (RemoveUConstrAt n _ l) = Eval (RemoveUConstrAt_ n l)
data RemoveUConstrAt_ (n :: Nat) :: MajorSurgery k
type instance Eval (RemoveUConstrAt_ n (M1 i m f)) = M1 i m (Eval (RemoveUConstrAt_ n f))
type instance Eval (RemoveUConstrAt_ n (f :+: g)) =
Eval (If (n == 0) (Pure g) ((:+:) f <$> RemoveUConstrAt_ (n-1) g))
data InsertConstrAt (c :: sym) (n :: Nat) (t :: ty) :: MajorSurgery k
type instance Eval (InsertConstrAt c n t l) = Eval (InsertUConstrAtL n (ConGraft c t) l)
type family ConGraft (c :: sym) (t :: ty) :: k -> Type
type instance ConGraft c (t :: Type) = RenameCon c (Linearize (UnM1 (Rep t)))
type family RenameCon (c :: sym) (t :: k -> Type) :: k -> Type
type instance RenameCon c (M1 C m f) = M1 C (RenameMeta c m) f
type family RenameMeta (c :: sym) (m :: Meta) :: Meta
type instance RenameMeta (s :: Symbol) ('MetaCons _ _ r) = 'MetaCons s 'PrefixI r
type instance PerformL l (InsertConstrAt c n t) = PerformLInsertConstrAt0 l c n t
type PerformLInsertConstrAt0 l c n t =
PerformLInsertConstrAt c n t (ConGraft c t) l (Eval (InsertUConstrAtL n (ConGraft c t) l))
type PerformLInsertConstrAt_ c n t l_t l lc =
( GInsertConstr n t l lc
, c ~ MetaConsName (MetaOf l_t)
, n ~ (ConstrIndex c @@ lc)
, l_t ~ (ConstrAt n @@ lc)
, l ~ Eval (RemoveUConstrAt_ n lc)
, MatchFields (Linearize (UnM1 (Rep t))) l_t
)
class PerformLInsertConstrAt_ c n t l_t l lc => PerformLInsertConstrAt c n t l_t l lc
instance PerformLInsertConstrAt_ c n t l_t l lc => PerformLInsertConstrAt c n t l_t l lc
data InsertUConstrAt (n :: Nat) (t :: Type) :: MajorSurgery k
type instance Eval (InsertUConstrAt n t l) = Eval (InsertUConstrAtL n (Linearize (UnM1 (Rep t))) l)
data InsertUConstrAtL (n :: Nat) (t :: k -> Type) :: MajorSurgery k
type instance Eval (InsertUConstrAtL n t (M1 i m f)) = M1 i m (Eval (InsertUConstrAtL n t f))
type instance Eval (InsertUConstrAtL n t (f :+: g)) =
Eval (If (n == 0) (Pure (t :+: (f :+: g))) ((:+:) f <$> InsertUConstrAtL (n-1) t g))
type instance Eval (InsertUConstrAtL 0 t V1) = t :+: V1
data ConstrIndex (con :: Symbol) (f :: k -> Type) :: Exp Nat
type instance Eval (ConstrIndex con (M1 D m f)) = Eval (ConstrIndex con f)
type instance Eval (ConstrIndex con (M1 C ('MetaCons con' fx s) f :+: g)) =
Eval (If (con == con') (Pure 0) (Succ =<< ConstrIndex con g))
class GRemoveConstr (n :: Nat) (t :: Type) f g where
gRemoveConstr :: f x -> Either t (g x)
instance GRemoveConstr n t f g => GRemoveConstr n t (M1 i c f) (M1 i c g) where
gRemoveConstr (M1 a) = M1 <$> gRemoveConstr @n a
type ConstrArborify t l =
( Generic t
, Coercible (UnM1 (Rep t)) (Rep t)
, GArborify (UnM1 (Rep t))
, Coercible l (Linearize (UnM1 (Rep t)))
)
constrArborify' :: forall t l x. ConstrArborify t l => l x -> t
constrArborify' = to @t @x . coerce (gArborify @(UnM1 (Rep t)) @x)
instance ConstrArborify t l => GRemoveConstr 0 t (l :+: f) f where
gRemoveConstr (L1 a) = Left (constrArborify' a)
gRemoveConstr (R1 b) = Right b
instance {-# OVERLAPPABLE #-}
( GRemoveConstr (n-1) t f g, (n == 0) ~ 'False
, f0g ~ (f0 :+: g)
) => GRemoveConstr n t (f0 :+: f) f0g where
gRemoveConstr (L1 a) = Right (L1 a)
gRemoveConstr (R1 b) = R1 <$> gRemoveConstr @(n-1) b
class GInsertConstr (n :: Nat) (t :: Type) f g where
gInsertConstr :: Either t (f x) -> g x
instance GInsertConstr n t f g => GInsertConstr n t (M1 i c f) (M1 i c g) where
gInsertConstr = M1 . gInsertConstr @n . fmap unM1
type ConstrLinearize t l =
( Generic t
, Coercible (Rep t) (UnM1 (Rep t))
, GLinearize (UnM1 (Rep t))
, Coercible (Linearize (UnM1 (Rep t))) l
)
constrLinearize' :: forall t l x. ConstrLinearize t l => t -> l x
constrLinearize' = coerce (gLinearize @(UnM1 (Rep t)) @x) . from @t @x
instance ConstrLinearize t l => GInsertConstr 0 t f (l :+: f) where
gInsertConstr (Left a) = L1 (constrLinearize' a)
gInsertConstr (Right b) = R1 b
instance {-# OVERLAPPABLE #-}
( GInsertConstr (n-1) t f g, (n == 0) ~ 'False
, f0f ~ (f0 :+: f)
) => GInsertConstr n t f0f (f0 :+: g) where
gInsertConstr (Left a) = R1 (gInsertConstr @(n-1) @t @f @g (Left a))
gInsertConstr (Right (L1 a)) = L1 a
gInsertConstr (Right (R1 b)) = R1 (gInsertConstr @(n-1) @t @f @g (Right b))
class MatchFields (f :: k -> Type) (g :: k -> Type)
instance (g ~ M1 D c g', MatchFields f' g') => MatchFields (M1 D c f') g
instance (g ~ M1 C ('MetaCons _x _y _z) g', MatchFields f' g') => MatchFields (M1 C c f') g
instance (g ~ M1 S ('MetaSel _w _x _y _z) g', MatchFields f' g') => MatchFields (M1 S c f') g
instance (g ~ (g1 :+: g2), MatchFields f1 g1, MatchFields f2 g2) => MatchFields (f1 :+: f2) g
instance (g ~ (g1 :*: g2), MatchFields f1 g1, MatchFields f2 g2) => MatchFields (f1 :*: f2) g
instance (g ~ K1 i a) => MatchFields (K1 i a) g
instance (g ~ U1) => MatchFields U1 g
instance (g ~ V1) => MatchFields V1 g
class IsTuple (n :: Nat) (t :: k)
instance (t ~ ()) => IsTuple 0 t
instance (t ~ Identity a) => IsTuple 1 t
instance (t ~ (a, b)) => IsTuple 2 t
instance (t ~ (a, b, c)) => IsTuple 3 t
instance (t ~ (a, b, c, d)) => IsTuple 4 t
instance (t ~ (a, b, c, d, e)) => IsTuple 5 t
instance (t ~ (a, b, c, d, e, f)) => IsTuple 6 t
instance (t ~ (a, b, c, d, e, f, g)) => IsTuple 7 t