module Data.HList.RecordU where
import Data.Array.Unboxed
import Data.HList.FakePrelude
import Data.HList.Record
import Data.HList.HList
import Data.HList.HArray
import LensDefs
import Data.HList.Labelable
import Unsafe.Coerce
import GHC.Exts (Any)
newtype RecordUS (x :: [*]) =
RecordUS Any
class RecordUSCxt (x :: [*]) (u :: [*]) | x -> u, u -> x where
recordUSToHList :: RecordUS x -> HList u
recordUSToHList (RecordUS x) = unsafeCoerce x
hListToRecordUS :: HList u -> RecordUS x
hListToRecordUS x = RecordUS (unsafeCoerce x)
instance (HGroupBy EqTagValue x g, HMapUnboxF g u) => RecordUSCxt x u
data EqTagValue
instance HEqByFn EqTagValue
instance (txv ~ Tagged x v,
tyw ~ Tagged y w,
HEq v w b) => HEqBy EqTagValue txv tyw b
class HMapUnboxF (xs :: [*]) (us :: [*]) | xs -> us, us -> xs
instance HMapUnboxF '[] '[]
instance HMapUnboxF xs us => HMapUnboxF (HList x ': xs) (RecordU x ': us)
instance (RecordUSCxt x u, Show (HList u)) => Show (RecordUS x) where
showsPrec n r = ("RecordUS " ++) . showsPrec n (recordUSToHList r)
newtype RecordU l = RecordU (UArray Int (GetElemTy l))
type family GetElemTy (x :: [*]) :: *
type instance GetElemTy (Tagged label v ': rest) = v
deriving instance (Show (UArray Int (GetElemTy l))) => Show (RecordU l)
deriving instance (Read (UArray Int (GetElemTy l))) => Read (RecordU l)
deriving instance (Eq (UArray Int (GetElemTy l))) => Eq (RecordU l)
deriving instance (Ord (UArray Int (GetElemTy l))) => Ord (RecordU l)
class SortForRecordUS x x' | x -> x' where
sortForRecordUS :: Record x -> Record x'
instance SortForRecordUS '[] '[] where
sortForRecordUS = id
instance (HPartitionEq EqTagValue x (x ': xs) xi xo,
SortForRecordUS xo xo',
sorted ~ HAppendListR xi xo',
HAppendList xi xo') =>
SortForRecordUS (x ': xs) sorted where
sortForRecordUS (Record xs) = Record (hAppendList xi xo')
where
f = Proxy :: Proxy EqTagValue
x1 = Proxy :: Proxy x
(xi,xo) = hPartitionEq f x1 xs
Record xo' = sortForRecordUS (Record xo)
instance (HFindLabel l r n,
HLookupByHNatUS n u (Tagged l v),
HasField l (Record r) v,
RecordUSCxt r u) =>
HasField l (RecordUS r) v where
hLookupByLabel _ u = case hLookupByHNatUS n (recordUSToHList u) of Tagged v -> v
where n = Proxy :: Proxy n
class HLookupByHNatUS (n :: HNat) (us :: [*]) (e :: *) | n us -> e where
hLookupByHNatUS :: Proxy n -> HList us -> e
class HLookupByHNatUS1 (r :: Either HNat HNat) (n :: HNat) (u :: [*]) (us :: [*]) (e :: *)
| r n u us -> e where
hLookupByHNatUS1 :: Proxy r -> Proxy n -> RecordU u -> HList us -> e
instance (r ~ HSubtract (HLength u) n,
RecordU u ~ ru,
HLookupByHNatUS1 r n u us e) =>
HLookupByHNatUS n (ru ': us) e where
hLookupByHNatUS n (HCons u us) = hLookupByHNatUS1 (Proxy :: Proxy r) n u us
instance (HNat2Integral n,
HLookupByHNatR n u ~ le,
le ~ Tagged l e,
IArray UArray e,
e ~ GetElemTy u) => HLookupByHNatUS1 (Left t) n u us le where
hLookupByHNatUS1 _ n (RecordU u) _us = Tagged (u ! hNat2Integral n)
instance HLookupByHNatUS t us e => HLookupByHNatUS1 (Right t) n u us e where
hLookupByHNatUS1 _ _ _ = hLookupByHNatUS (Proxy :: Proxy t)
type family HSubtract (n1 :: HNat) (n2 :: HNat) :: Either HNat HNat
type instance HSubtract HZero HZero = Right HZero
type instance HSubtract (HSucc x) (HSucc y) = HSubtract x y
type instance HSubtract HZero (HSucc y) = Right (HSucc y)
type instance HSubtract (HSucc y) HZero = Left (HSucc y)
recordUS r = iso hListToRecordUS recordUSToHList r
recordUS' r = simple (recordUS r)
recordToRecordUS :: forall x g u.
(HMapCxt HList UnboxF g u,
HMapUnboxF g u,
HGroupBy EqTagValue x g,
RecordUSCxt x u)
=> Record x -> RecordUS x
recordToRecordUS (Record x) = hListToRecordUS u
where
u :: HList u
u = hMap UnboxF g
g :: HList g
g = hGroupBy (Proxy :: Proxy EqTagValue) x
recordUSToRecord :: forall u g x.
(HConcatFD g x,
HMapCxt HList BoxF u g,
HMapUnboxF g u,
RecordUSCxt x u
) => RecordUS x -> Record x
recordUSToRecord rus = Record (hConcatFD g)
where
g :: HList g
g = hMap BoxF (recordUSToHList rus)
unboxedS r = iso recordToRecordUS recordUSToRecord r
unboxedS' r = simple (unboxedS r)
class ElemTyEq (xs :: [*])
instance
(t1v ~ Tagged t1 v,
t2v ~ Tagged t2 v,
ElemTyEq (tv2 ': rest)) =>
ElemTyEq (tv1 ': tv2 ': rest)
instance t1v ~ Tagged t v => ElemTyEq (t1v ': rest)
instance ElemTyEq '[]
instance (IArray UArray v,
v ~ GetElemTy ls,
HFindLabel l ls n,
HNat2Integral n)
=> HasField l (RecordU ls) v where
hLookupByLabel _ (RecordU ls) = ls ! hNat2Integral (Proxy :: Proxy n)
instance (r ~ r',
v ~ GetElemTy r,
HFindLabel l r n,
HNat2Integral n,
IArray UArray v,
HasField l (Record r') v)
=> HUpdateAtLabel RecordU l v r r' where
hUpdateAtLabel _ v (RecordU r) = RecordU (r // [(hNat2Integral (Proxy :: Proxy n), v)])
class HUpdateMany lv rx where
hUpdateMany :: Record lv -> rx -> rx
instance (RecordValues lv,
HList2List (RecordValuesR lv) v,
HFindMany (LabelsOf lv) (LabelsOf r) ixs,
IArray UArray v,
v ~ GetElemTy r,
HNats2Integrals ixs) =>
HUpdateMany lv (RecordU r) where
hUpdateMany lv (RecordU r) = RecordU (r // (zip ixs (hList2List (recordValues lv))))
where ixs = hNats2Integrals (Proxy :: Proxy ixs)
instance (HLeftUnion lv x lvx,
HRLabelSet x,
HLabelSet (LabelsOf x),
HRearrange (LabelsOf x) lvx x)
=> HUpdateMany lv (Record x) where
hUpdateMany lv x = hRearrange' (lv .<++. x)
class HFindMany (ls :: [k]) (r :: [k]) (ns :: [HNat]) | ls r -> ns
instance (HFind l r n,
HFindMany ls r ns) => HFindMany (l ': ls) r (n ': ns)
instance HFindMany '[] r '[]
instance (ApplyAB f (GetElemTy x) (GetElemTy y),
IArray UArray (GetElemTy y),
IArray UArray (GetElemTy x)) => HMapAux RecordU f x y where
hMapAux f (RecordU x) = RecordU (amap (applyAB f) x)
hMapRU :: HMapCxt RecordU f x y => f -> RecordU x -> RecordU y
hMapRU f = hMap f
unboxed :: forall x y f p.
(Profunctor p,
Functor f,
RecordToRecordU x,
RecordUToRecord y)
=> RecordU x `p` f (RecordU y)
-> Record x `p` f (Record y)
unboxed r = iso recordToRecordU recordUToRecord r
unboxed' x = simple (unboxed x)
class RecordToRecordU x where
recordToRecordU :: Record x -> RecordU x
instance (
RecordValues x,
HList2List (RecordValuesR x) (GetElemTy x),
HNat2Integral n,
HLengthEq x n,
IArray UArray (GetElemTy x)
) => RecordToRecordU x where
recordToRecordU (rx @ (Record x)) = RecordU $ listArray
(0, hNat2Integral (hLength x) 1)
(hList2List (recordValues rx))
class RecordUToRecord x where
recordUToRecord :: RecordU x -> Record x
instance (
HMapCxt HList TaggedFn (RecordValuesR x) x,
IArray UArray (GetElemTy x),
HList2List (RecordValuesR x) (GetElemTy x)
) => RecordUToRecord x where
recordUToRecord (RecordU b) = case list2HList $ elems b of
Nothing -> error "Data.HList.RecordU.recordUToRecord impossibly too few elements"
Just y0 -> Record $ hMap TaggedFn (y0 :: HList (RecordValuesR x))
type Bad =
[Tagged "x" Double,
Tagged "i" Int,
Tagged "y" Double,
Tagged "j" Int]
bad :: Record Bad
bad = Tagged 1 .*. Tagged 2 .*. Tagged 3 .*. Tagged 4 .*. emptyRecord
bad1 :: Record [Tagged "x" Double, Tagged "y" Double]
bad1 = Tagged 1 .*. Tagged 2 .*. emptyRecord
data UnboxF = UnboxF
instance (hx ~ HList x, ux ~ RecordU x,
RecordToRecordU x) =>
ApplyAB UnboxF hx ux where
applyAB _ = recordToRecordU . Record
data BoxF = BoxF
instance (ux ~ RecordU x,
hx ~ HList x,
RecordUToRecord x) =>
ApplyAB BoxF ux hx where
applyAB _ ux = case recordUToRecord ux of Record hx -> hx
instance (s ~ t, a ~ b,
IArray UArray a, a ~ GetElemTy s,
HLensCxt x RecordU s t a b)
=> Labelable x RecordU s t a b where
type LabelableTy RecordU = LabelableLens
hLens' = hLens