{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}
module Database.Immutable.Internal where
import qualified Data.ByteString as B
import qualified Data.Serialize as S
import Data.Word
import qualified Data.Vector.Storable as V
import qualified Multimap.ByteString as MMB
import qualified Multimap.Word32 as MMW
import GHC.OverloadedLabels
import GHC.TypeLits
newtype Id a = Id { getId :: Word32 }
deriving (Eq, Ord, Show, S.Serialize)
zeroId :: Id a
zeroId = Id 0
incId :: Id a -> Id a
incId (Id i) = Id (i + 1)
coerceId :: Id a -> Id b
coerceId (Id i) = Id i
newtype Limit a = Limit { getLimit :: Word32 }
deriving (Eq, Ord, Show, S.Serialize)
addLimit :: Id a -> Limit a -> Id a
addLimit (Id a) (Limit b) = Id (a + b - 1)
subIds :: Id a -> Id a -> Limit a
subIds (Id a) (Id b) = Limit (a - b + 1)
data Name (a :: Symbol) = Name
instance l ~ l' => IsLabel (l :: Symbol) (Name l') where
fromLabel = Name
data DB (indexes :: [(Symbol, *)]) a
= DB (MapIndexes indexes a) B.ByteString (V.Vector Word32)
data Indexes (indexes :: [(Symbol, *)]) a = Indexes (IO (MapIndexes indexes a))
data Indexes' (indexes :: [(Symbol, *)]) a = Indexes' (MapIndexes indexes a)
data ByteStringIndex a = ByteStringIndex
data Word32Index a = Word32Index
type family Trd t where
Trd (a, b, c) = c
type family MapIndexes (indexes :: [(Symbol, *)]) a :: * where
MapIndexes '[] a = ()
MapIndexes ('(s, ByteStringIndex b):xs) a = ( MMB.Multimap
, a -> b
, b -> B.ByteString
, MapIndexes xs a
)
MapIndexes ('(s, Word32Index b):xs) a = ( MMW.Multimap
, a -> b
, b -> Word32
, MapIndexes xs a
)
class LookupIndex indexes (s :: Symbol) t a | indexes s a -> t where
lookupIndex :: Indexes' indexes a -> Name s -> t -> IO [Word32]
instance LookupIndex ('(s, Word32Index b):xs) s b a where
lookupIndex (Indexes' (mm, _, f, _)) _ = MMW.lookup mm . f
instance LookupIndex ('(s, ByteStringIndex b):xs) s b a where
lookupIndex (Indexes' (mm, _, f, _)) _ = MMB.lookup mm . f
instance {-# OVERLAPPABLE #-}
( MapIndexes (x:xs) a ~ (y, u, w, MapIndexes xs a)
, LookupIndex xs s t a
) => LookupIndex (x:xs) s t a where
lookupIndex (Indexes' (_, _, _, xs))
= lookupIndex (Indexes' xs :: Indexes' xs a)
class InsertIndex indexes a where
insertIndex :: Indexes' indexes a -> Word32 -> a -> IO ()
instance InsertIndex '[] a where
insertIndex _ _ _ = pure ()
instance ( MapIndexes ('(s, Word32Index b) : xs) a ~ (MMW.Multimap, a -> b, b -> Word32, MapIndexes xs a)
, InsertIndex xs a
) => InsertIndex ('(s, Word32Index b):xs) a where
insertIndex (Indexes' (mm, p, f, xs)) index a = do
MMW.insert mm (f $ p a) index
insertIndex (Indexes' xs :: Indexes' xs a) index a
instance ( MapIndexes ('(s, ByteStringIndex b) : xs) a ~ (MMB.Multimap, a -> b, b -> B.ByteString, MapIndexes xs a)
, InsertIndex xs a
) => InsertIndex ('(s, ByteStringIndex b):xs) a where
insertIndex (Indexes' (mm, p, f, xs)) index a = do
MMB.insert mm (f $ p a) index
insertIndex (Indexes' xs :: Indexes' xs a) index a