{-# LANGUAGE ConstraintKinds, DataKinds, FlexibleContexts, FlexibleInstances,
KindSignatures, MultiParamTypeClasses, PolyKinds,
ScopedTypeVariables, TypeFamilies, TypeOperators,
UndecidableInstances #-}
module Frames.Melt where
import Data.Proxy
import Data.Vinyl
import Data.Vinyl.CoRec (CoRec(..))
import Data.Vinyl.TypeLevel
import Frames.Col
import Frames.Frame (Frame(..), FrameRec)
import Frames.Rec
import Frames.RecF (ColumnHeaders(..))
type family Elem t ts :: Bool where
Elem t '[] = 'False
Elem t (t ': ts) = 'True
Elem t (s ': ts) = Elem t ts
type family Or (a :: Bool) (b :: Bool) :: Bool where
Or 'True b = 'True
Or a b = b
type family Not a :: Bool where
Not 'True = 'False
Not 'False = 'True
type family Disjoint ss ts :: Bool where
Disjoint '[] ts = 'True
Disjoint (s ': ss) ts = Or (Not (Elem s ts)) (Disjoint ss ts)
type ElemOf ts r = RElem r ts (RIndex r ts)
class RowToColumn ts rs where
rowToColumnAux :: Proxy ts -> Rec f rs -> [CoRec f ts]
instance RowToColumn ts '[] where
rowToColumnAux :: Proxy ts -> Rec f '[] -> [CoRec f ts]
rowToColumnAux Proxy ts
_ Rec f '[]
_ = []
instance (r ∈ ts, RowToColumn ts rs) => RowToColumn ts (r ': rs) where
rowToColumnAux :: Proxy ts -> Rec f (r : rs) -> [CoRec f ts]
rowToColumnAux Proxy ts
p (f r
x :& Rec f rs
xs) = f r -> CoRec f ts
forall k (a1 :: k) (b :: [k]) (a :: k -> *).
RElem a1 b (RIndex a1 b) =>
a a1 -> CoRec a b
CoRec f r
x CoRec f ts -> [CoRec f ts] -> [CoRec f ts]
forall a. a -> [a] -> [a]
: Proxy ts -> Rec f rs -> [CoRec f ts]
forall k (ts :: [k]) (rs :: [k]) (f :: k -> *).
RowToColumn ts rs =>
Proxy ts -> Rec f rs -> [CoRec f ts]
rowToColumnAux Proxy ts
p Rec f rs
xs
rowToColumn :: RowToColumn ts ts => Rec f ts -> [CoRec f ts]
rowToColumn :: Rec f ts -> [CoRec f ts]
rowToColumn = Proxy ts -> Rec f ts -> [CoRec f ts]
forall k (ts :: [k]) (rs :: [k]) (f :: k -> *).
RowToColumn ts rs =>
Proxy ts -> Rec f rs -> [CoRec f ts]
rowToColumnAux Proxy ts
forall k (t :: k). Proxy t
Proxy
meltAux :: forall vs ss ts.
(vs ⊆ ts, ss ⊆ ts, Disjoint ss ts ~ 'True, ts ≅ (vs ++ ss),
ColumnHeaders vs, RowToColumn vs vs)
=> Record ts
-> [Record ("value" :-> CoRec ElField vs ': ss)]
meltAux :: Record ts -> [Record (("value" :-> CoRec ElField vs) : ss)]
meltAux Record ts
r = (CoRec ElField vs -> Record (("value" :-> CoRec ElField vs) : ss))
-> [CoRec ElField vs]
-> [Record (("value" :-> CoRec ElField vs) : ss)]
forall a b. (a -> b) -> [a] -> [b]
map (\CoRec ElField vs
val -> CoRec ElField vs -> ElField ("value" :-> CoRec ElField vs)
forall (s :: Symbol) t. KnownSymbol s => t -> ElField '(s, t)
Field CoRec ElField vs
val ElField ("value" :-> CoRec ElField vs)
-> Rec ElField ss -> Record (("value" :-> CoRec ElField vs) : ss)
forall u (a :: u -> *) (r :: u) (rs :: [u]).
a r -> Rec a rs -> Rec a (r : rs)
:& Rec ElField ss
ids) (Rec ElField vs -> [CoRec ElField vs]
forall k (ts :: [k]) (f :: k -> *).
RowToColumn ts ts =>
Rec f ts -> [CoRec f ts]
rowToColumn Rec ElField vs
vals)
where ids :: Rec ElField ss
ids = Record ts -> Rec ElField ss
forall k1 k2 (rs :: [k1]) (ss :: [k1]) (f :: k2 -> *)
(record :: (k2 -> *) -> [k1] -> *) (is :: [Nat]).
(RecSubset record rs ss is, RecSubsetFCtx record f) =>
record f ss -> record f rs
rcast Record ts
r :: Record ss
vals :: Rec ElField vs
vals = Record ts -> Rec ElField vs
forall k1 k2 (rs :: [k1]) (ss :: [k1]) (f :: k2 -> *)
(record :: (k2 -> *) -> [k1] -> *) (is :: [Nat]).
(RecSubset record rs ss is, RecSubsetFCtx record f) =>
record f ss -> record f rs
rcast Record ts
r :: Record vs
type family RDeleteAll ss ts where
RDeleteAll '[] ts = ts
RDeleteAll (s ': ss) ts = RDeleteAll ss (RDelete s ts)
meltRow' :: forall proxy vs ts ss. (vs ⊆ ts, ss ⊆ ts, vs ~ RDeleteAll ss ts,
Disjoint ss ts ~ 'True, ts ≅ (vs ++ ss),
ColumnHeaders vs, RowToColumn vs vs)
=> proxy ss
-> Record ts
-> [Record ("value" :-> CoRec ElField vs ': ss)]
meltRow' :: proxy ss
-> Record ts -> [Record (("value" :-> CoRec ElField vs) : ss)]
meltRow' proxy ss
_ = Record ts -> [Record (("value" :-> CoRec ElField vs) : ss)]
forall (vs :: [(Symbol, *)]) (ss :: [(Symbol, *)])
(ts :: [(Symbol, *)]).
(vs ⊆ ts, ss ⊆ ts, Disjoint ss ts ~ 'True, ts ≅ (vs ++ ss),
ColumnHeaders vs, RowToColumn vs vs) =>
Record ts -> [Record (("value" :-> CoRec ElField vs) : ss)]
meltAux
retroSnoc :: forall t ts. Record (t ': ts) -> Record (ts ++ '[t])
retroSnoc :: Record (t : ts) -> Record (ts ++ '[t])
retroSnoc (ElField r
x :& Rec ElField rs
xs) = Rec ElField rs -> Record (rs ++ '[t])
forall (ss :: [(Symbol, *)]). Record ss -> Record (ss ++ '[t])
go Rec ElField rs
xs
where go :: Record ss -> Record (ss ++ '[t])
go :: Record ss -> Record (ss ++ '[t])
go Record ss
RNil = ElField r
x ElField r -> Rec ElField '[] -> Rec ElField '[r]
forall u (a :: u -> *) (r :: u) (rs :: [u]).
a r -> Rec a rs -> Rec a (r : rs)
:& Rec ElField '[]
forall u (a :: u -> *). Rec a '[]
RNil
go (ElField r
y :& Rec ElField rs
ys) = ElField r
y ElField r
-> Rec ElField (rs ++ '[t]) -> Rec ElField (r : (rs ++ '[t]))
forall u (a :: u -> *) (r :: u) (rs :: [u]).
a r -> Rec a rs -> Rec a (r : rs)
:& Rec ElField rs -> Rec ElField (rs ++ '[t])
forall (ss :: [(Symbol, *)]). Record ss -> Record (ss ++ '[t])
go Rec ElField rs
ys
meltRow :: (vs ⊆ ts, ss ⊆ ts, vs ~ RDeleteAll ss ts,
Disjoint ss ts ~ 'True, ts ≅ (vs ++ ss),
ColumnHeaders vs, RowToColumn vs vs)
=> proxy ss
-> Record ts
-> [Record (ss ++ '["value" :-> CoRec ElField vs])]
meltRow :: proxy ss
-> Record ts -> [Record (ss ++ '["value" :-> CoRec ElField vs])]
meltRow = ((Record (("value" :-> CoRec ElField vs) : ss)
-> Record (ss ++ '["value" :-> CoRec ElField vs]))
-> [Record (("value" :-> CoRec ElField vs) : ss)]
-> [Record (ss ++ '["value" :-> CoRec ElField vs])]
forall a b. (a -> b) -> [a] -> [b]
map Record (("value" :-> CoRec ElField vs) : ss)
-> Record (ss ++ '["value" :-> CoRec ElField vs])
forall (t :: (Symbol, *)) (ts :: [(Symbol, *)]).
Record (t : ts) -> Record (ts ++ '[t])
retroSnoc ([Record (("value" :-> CoRec ElField vs) : ss)]
-> [Record (ss ++ '["value" :-> CoRec ElField vs])])
-> (Record ts -> [Record (("value" :-> CoRec ElField vs) : ss)])
-> Record ts
-> [Record (ss ++ '["value" :-> CoRec ElField vs])]
forall b c a. (b -> c) -> (a -> b) -> a -> c
.) ((Record ts -> [Record (("value" :-> CoRec ElField vs) : ss)])
-> Record ts -> [Record (ss ++ '["value" :-> CoRec ElField vs])])
-> (proxy ss
-> Record ts -> [Record (("value" :-> CoRec ElField vs) : ss)])
-> proxy ss
-> Record ts
-> [Record (ss ++ '["value" :-> CoRec ElField vs])]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. proxy ss
-> Record ts -> [Record (("value" :-> CoRec ElField vs) : ss)]
forall (proxy :: [(Symbol, *)] -> *) (vs :: [(Symbol, *)])
(ts :: [(Symbol, *)]) (ss :: [(Symbol, *)]).
(vs ⊆ ts, ss ⊆ ts, vs ~ RDeleteAll ss ts, Disjoint ss ts ~ 'True,
ts ≅ (vs ++ ss), ColumnHeaders vs, RowToColumn vs vs) =>
proxy ss
-> Record ts -> [Record (("value" :-> CoRec ElField vs) : ss)]
meltRow'
class HasLength (ts :: [k]) where
hasLength :: proxy ts -> Int
instance HasLength '[] where hasLength :: proxy '[] -> Int
hasLength proxy '[]
_ = Int
0
instance forall t ts. HasLength ts => HasLength (t ': ts) where
hasLength :: proxy (t : ts) -> Int
hasLength proxy (t : ts)
_ = Int
1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Proxy ts -> Int
forall k (ts :: [k]) (proxy :: [k] -> *).
HasLength ts =>
proxy ts -> Int
hasLength (Proxy ts
forall k (t :: k). Proxy t
Proxy :: Proxy ts)
melt :: forall vs ts ss proxy.
(vs ⊆ ts, ss ⊆ ts, vs ~ RDeleteAll ss ts, HasLength vs,
Disjoint ss ts ~ 'True, ts ≅ (vs ++ ss),
ColumnHeaders vs, RowToColumn vs vs)
=> proxy ss
-> FrameRec ts
-> FrameRec (ss ++ '["value" :-> CoRec ElField vs])
melt :: proxy ss
-> FrameRec ts -> FrameRec (ss ++ '["value" :-> CoRec ElField vs])
melt proxy ss
p (Frame Int
n Int -> Record ts
v) = Int
-> (Int -> Record (ss ++ '["value" :-> CoRec ElField vs]))
-> FrameRec (ss ++ '["value" :-> CoRec ElField vs])
forall r. Int -> (Int -> r) -> Frame r
Frame (Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
*Int
numVs) Int -> Record (ss ++ '["value" :-> CoRec ElField vs])
go
where numVs :: Int
numVs = Proxy vs -> Int
forall k (ts :: [k]) (proxy :: [k] -> *).
HasLength ts =>
proxy ts -> Int
hasLength (Proxy vs
forall k (t :: k). Proxy t
Proxy :: Proxy vs)
go :: Int -> Record (ss ++ '["value" :-> CoRec ElField vs])
go Int
i = let (Int
j,Int
k) = Int
i Int -> Int -> (Int, Int)
forall a. Integral a => a -> a -> (a, a)
`quotRem` Int
numVs
in proxy ss
-> Record ts -> [Record (ss ++ '["value" :-> CoRec ElField vs])]
forall (vs :: [(Symbol, *)]) (ts :: [(Symbol, *)])
(ss :: [(Symbol, *)]) (proxy :: [(Symbol, *)] -> *).
(vs ⊆ ts, ss ⊆ ts, vs ~ RDeleteAll ss ts, Disjoint ss ts ~ 'True,
ts ≅ (vs ++ ss), ColumnHeaders vs, RowToColumn vs vs) =>
proxy ss
-> Record ts -> [Record (ss ++ '["value" :-> CoRec ElField vs])]
meltRow proxy ss
p (Int -> Record ts
v Int
j) [Record (ss ++ '["value" :-> CoRec ElField vs])]
-> Int -> Record (ss ++ '["value" :-> CoRec ElField vs])
forall a. [a] -> Int -> a
!! Int
k