module Data.HList.TIP
(module Data.HList.TIPtuple,
module Data.HList.TIP) where
import Data.HList.HListPrelude
import Data.HList.FakePrelude
import Data.HList.HList
import Data.HList.Record
import Data.HList.HTypeIndexed ()
import Data.HList.TIPtuple
import Data.List (intercalate)
import Data.Array (Ix)
import Data.Semigroup (Semigroup)
#if __GLASGOW_HASKELL__ > 710
import Data.Coerce
#endif
import LensDefs
newtype TIP (l :: [*]) = TIP{unTIP:: HList l}
deriving instance Semigroup (HList a) => Semigroup (TIP a)
deriving instance Monoid (HList a) => Monoid (TIP a)
deriving instance Eq (HList a) => Eq (TIP a)
deriving instance (Ord (HList r)) => Ord (TIP r)
deriving instance (Ix (HList r)) => Ix (TIP r)
deriving instance (Bounded (HList r)) => Bounded (TIP r)
instance HMapOut (HShow `HComp` HUntag) l String => Show (TIP l) where
showsPrec _ (TIP l) = ("TIPH[" ++)
. (intercalate "," (hMapOut (HShow `HComp` HUntag) l) ++)
. (']' :)
mkTIP :: HTypeIndexed l => HList l -> TIP l
mkTIP = TIP
emptyTIP :: TIP '[]
emptyTIP = mkTIP HNil
class (HAllTaggedEq l, HRLabelSet l) => HTypeIndexed (l :: [*])
instance (HAllTaggedEq l, HRLabelSet l) => HTypeIndexed l
class HAllTaggedEq (l :: [*])
instance HAllTaggedEq '[]
instance (HAllTaggedEq l, tee ~ Tagged e e') => HAllTaggedEq (tee ': l)
instance (HRLabelSet (Tagged e e ': l), HTypeIndexed l) => HExtend e (TIP l)
where
type HExtendR e (TIP l) = TIP (Tagged e e ': l)
e .*. TIP l = mkTIP (HCons (Tagged e) l)
instance (e ~ e', HasField e (Record l) e') => HasField e (TIP l) e' where
hLookupByLabel lab (TIP l) = hLookupByLabel lab (Record l)
instance (tee ~ Tagged e e) => HOccurs e (TIP '[tee]) where
hOccurs (TIP (HCons (Tagged e) _)) = e
instance HasField e (Record (x ': y ': l)) e
=> HOccurs e (TIP (x ': y ': l)) where
hOccurs (TIP l) = Record l .!. (Label :: Label e)
instance (HAppend (HList l) (HList l'), HTypeIndexed (HAppendListR l l'))
=> HAppend (TIP l) (TIP l')
where
hAppend (TIP l) (TIP l') = mkTIP (hAppend l l')
type instance HAppendR (TIP l) (TIP l') = TIP (HAppendListR l l')
onRecord f (TIP l) = let Record l' = f (Record l) in mkTIP l'
instance (HDeleteAtLabel Record e v v',
HTypeIndexed v')
=> HDeleteAtLabel TIP e v v' where
hDeleteAtLabel e v = onRecord (hDeleteAtLabel e) v
tipyUpdate e t = hTPupdateAtLabel (fromValue e) e t
where fromValue :: e -> Label e
fromValue _ = Label
instance (HUpdateAtLabel Record e' e r r',
HTypeIndexed r',
e ~ e') => HUpdateAtLabel TIP e' e r r' where
hUpdateAtLabel l e r = onRecord (hUpdateAtLabel l e) r
tipyProject ps t = onRecord (hProjectByLabels ps) t
#if __GLASGOW_HASKELL__ < 707
tipyLens' x = isSimple tipyLens x
#else
tipyLens' f s = isSimple (hLens x) f (asTIP s)
where
x = getA f
getA :: (a -> f a) -> Label a
getA _ = Label
asTIP :: TIP a -> TIP a
asTIP = id
#endif
tipyLens f (TIP s) =
case hSplitAt (getN s f) (ghc8fix1 s) of
(x, ta @ (Tagged a) `HCons` ys)
| () <- ghc8fix2 ta ->
let mkt b = mkTIP (x `hAppendList` (tagSelf b `HCons` ys))
in mkt <$> f a
where
getN :: HFind (Label a) (LabelsOf s) n => HList s -> (a -> f b) -> Proxy n
getN _ _ = Proxy
ghc8fix1 :: HList (Tagged x x ': xs) -> HList (Tagged x x ': xs)
ghc8fix1 = id
ghc8fix2 :: Tagged a a -> ()
ghc8fix2 _ = ()
tipyProject2 ps (TIP l) = (mkTIP l',mkTIP l'')
where
(l',l'') = h2projectByLabels ps l
instance SubType (TIP l) (TIP '[])
instance (HOccurs e (TIP l1), SubType (TIP l1) (TIP l2))
=> SubType (TIP l1) (TIP (e ': l2))
class SameLength a ta => TagUntagFD a ta | a -> ta, ta -> a where
hTagSelf :: HList a -> HList ta
hUntagSelf :: HList ta -> HList a
instance TagUntagFD '[] '[] where
hTagSelf _ = HNil
hUntagSelf _ = HNil
instance (TagUntagFD xs ys, txx ~ Tagged x x)
=> TagUntagFD (x ': xs) (txx ': ys) where
hTagSelf (HCons x xs) = Tagged x `HCons` hTagSelf xs
hUntagSelf (HCons (Tagged x) xs) = x `HCons` hUntagSelf xs
type TagUntag xs = TagUntagFD xs (TagR xs)
type UntagTag xs = (TagR (UntagR xs) ~ xs, TagUntagFD (UntagR xs) xs)
type family TagR (a :: [*]) :: [*]
type family UntagR (ta :: [*]) :: [*]
type instance TagR '[] = '[]
type instance UntagR '[] = '[]
type instance TagR (x ': xs) = Tagged x x ': TagR xs
type instance UntagR (Tagged y y ': ys) = y ': UntagR ys
type family Untag1 (x :: *) :: *
type instance Untag1 (Tagged k x) = x
tipHList x = iso (\(TIP a) -> hUntagSelf a) (TIP . hTagSelf) x
tipHList' x = isSimple tipHList x
tipRecord x = isoNewtype (\(TIP a) -> Record a) (\(Record b) -> TIP b) x
tipRecord' x = isSimple tipRecord x
#if __GLASGOW_HASKELL__ < 800
instance (HZipList (UntagR x) (UntagR y) (UntagR xy),
UntagTag x, UntagTag y, UntagTag xy,
SameLengths [x,y,xy],
HTypeIndexed x, HTypeIndexed y,
HUnzip TIP x y xy
) => HZip TIP x y xy where
hZip = hZipTIP
instance (HZipList (UntagR x) (UntagR y) (UntagR xy),
UntagTag x, UntagTag y, UntagTag xy,
HTypeIndexed x, HTypeIndexed y,
SameLengths [x,y,xy]) => HUnzip TIP x y xy where
hUnzip = hUnzipTIP
#else
instance (HZipList xL yL xyL,
lty ~ (HList xyL -> (HList xL,HList yL)),
Coercible lty (TIP xy -> (TIP x, TIP y)),
UntagR x ~ xL, TagR xL ~ x,
UntagR y ~ yL, TagR yL ~ y,
UntagR xy ~ xyL, TagR xyL ~ xy,
SameLengths '[x,y,xy],
UntagTag x, UntagTag y, UntagTag xy
) => HUnzip TIP x y xy where
hUnzip = coerce (hUnzipList :: lty)
instance (HUnzip TIP x y xy,
HZipList xL yL xyL,
lty ~ (HList xL -> HList yL -> HList xyL),
Coercible lty (TIP x -> TIP y -> TIP xy) ,
UntagR x ~ xL,
UntagR y ~ yL,
UntagR xy ~ xyL,
UntagTag x, UntagTag y, UntagTag xy
) => HZip TIP x y xy where
hZip = coerce (hZipList :: lty)
#endif
hZipTIP (TIP x) (TIP y) = TIP (hTagSelf (hZipList (hUntagSelf x) (hUntagSelf y)))
hUnzipTIP (TIP xy) = case hUnzipList (hUntagSelf xy) of
(x,y) -> (mkTIP (hTagSelf x), mkTIP (hTagSelf y))
class TransTIP op db where
ttip :: op -> TIP db -> TIP db
instance (HMember (Tagged op op) db b,
Arity op n,
TransTIP1 b n op db)
=> TransTIP op db where
ttip = ttip1 (Proxy ::Proxy b) (Proxy :: Proxy n)
class TransTIP1 (b :: Bool) (n :: HNat) op db where
ttip1 :: Proxy b -> Proxy n -> op -> TIP db -> TIP db
instance HTPupdateAtLabel TIP op op db
=> TransTIP1 True n op db where
ttip1 _ _ = tipyUpdate
instance (HMember (Tagged arg arg) db b,
TransTIP2 b arg op db)
=> TransTIP1 False (HSucc n) (arg -> op) db where
ttip1 _ _ = ttip2 (Proxy :: Proxy b)
instance Fail (FieldNotFound notfun (TIP db))
=> TransTIP1 False HZero notfun db where
ttip1 = error "TransTIP1 Fail failed"
class TransTIP2 (b :: Bool) arg op db where
ttip2 :: Proxy b -> (arg -> op) -> TIP db -> TIP db
instance (HOccurs arg (TIP db),
TransTIP op db)
=> TransTIP2 True arg op db where
ttip2 _ f db = ttip (f (hOccurs db)) db
instance Fail (FieldNotFound arg (TIP db))
=> TransTIP2 False arg op db where
ttip2 = error "TransTIP2 Fail failed"
class Monad m => TransTIPM m op db where
ttipM :: op -> TIP db -> m (TIP db)
instance (Monad m, HMember (Tagged op op) db b,
Arity (m' op) n,
TransTIPM1 b n m (m' op) db)
=> TransTIPM m (m' op) db where
ttipM = ttipM1 (Proxy :: Proxy b) (Proxy :: Proxy n)
class Monad m => TransTIPM1 (b :: Bool) (n :: HNat) m op db where
ttipM1 :: Proxy b -> Proxy n -> op -> TIP db -> m (TIP db)
instance (Monad m, m ~ m', HTPupdateAtLabel TIP op op db)
=> TransTIPM1 True n m (m' op) db where
ttipM1 _ _ op db = do
op' <- op
return $ tipyUpdate op' db
instance (Fail (FieldNotFound op (TIP db)), Monad m)
=> TransTIPM1 False HZero m op db where
ttipM1 _ _ = error "TransTIPM1 Fail failed"
instance (Monad m,
HMember (Tagged arg arg) db b,
TransTIPM2 b m arg op db)
=> TransTIPM1 False (HSucc n) m (arg-> op) db where
ttipM1 _ _ = ttipM2 (Proxy :: Proxy b)
class TransTIPM2 (b :: Bool) m arg op db where
ttipM2 :: Proxy b -> (arg -> op) -> TIP db -> m (TIP db)
instance (HOccurs arg (TIP db), TransTIPM m op db)
=> TransTIPM2 True m arg op db where
ttipM2 _ f db = ttipM (f (hOccurs db)) db
instance Fail (FieldNotFound op (TIP db))
=> TransTIPM2 False m arg op db where
ttipM2 _ _ = error "TransTIPM1 Fail failed"
_ = tipyTuple ( '1' .*. True .*. emptyTIP ) :: (Char, Bool)
_ = tipyTuple ( '1' .*. True .*. emptyTIP ) :: (Bool, Char)