-- | A linear 0-based int-index with a phantom type. module Data.PrimitiveArray.Index.PhantomInt where import Control.DeepSeq (NFData(..)) import Data.Aeson (FromJSON,FromJSONKey,ToJSON,ToJSONKey) import Data.Binary (Binary) import Data.Data import Data.Hashable (Hashable) import Data.Ix(Ix) import Data.Serialize (Serialize) import Data.Typeable import Data.Vector.Fusion.Stream.Monadic (map,Step(..),flatten) import Data.Vector.Unboxed.Deriving import GHC.Generics (Generic) import Prelude hiding (map) import Data.PrimitiveArray.Index.Class import Data.PrimitiveArray.Index.IOC -- | A 'PInt' behaves exactly like an @Int@, but has an attached phantom -- type @p@. In particular, the @Index@ and @IndexStream@ instances are the -- same as for raw @Int@s. newtype PInt (ioc ∷ k) (p ∷ k) = PInt { getPInt :: Int } deriving stock (Read,Show,Eq,Ord,Generic,Data,Typeable,Ix) deriving newtype (Real,Num,Enum,Integral) pIntI :: Int -> PInt I p pIntI = PInt {-# Inline pIntI #-} pIntO :: Int -> PInt O p pIntO = PInt {-# Inline pIntO #-} pIntC :: Int -> PInt C p pIntC = PInt {-# Inline pIntC #-} derivingUnbox "PInt" [t| forall t p . PInt t p -> Int |] [| getPInt |] [| PInt |] instance Binary (PInt t p) instance Serialize (PInt t p) instance FromJSON (PInt t p) instance FromJSONKey (PInt t p) instance ToJSON (PInt t p) instance ToJSONKey (PInt t p) instance Hashable (PInt t p) instance NFData (PInt t p) instance Index (PInt t p) where newtype LimitType (PInt t p) = LtPInt Int linearIndex _ (PInt k) = k {-# Inline linearIndex #-} size (LtPInt h) = h+1 {-# Inline size #-} inBounds (LtPInt h) (PInt k) = 0 <= k && k <= h {-# Inline inBounds #-} fromLinearIndex = error "implement me" zeroBound = error "implement me" zeroBound' = error "implement me" totalSize = error "implement me" showBound = error "implement me" showIndex = error "implement me" deriving instance Show (LimitType (PInt t p)) deriving instance Read (LimitType (PInt t p)) deriving instance Eq (LimitType (PInt t p)) deriving instance Generic (LimitType (PInt t p)) instance IndexStream z => IndexStream (z:.PInt I p) where streamUp (ls:..LtPInt l) (hs:..LtPInt h) = flatten (streamUpMk l h) (streamUpStep l h) $ streamUp ls hs streamDown (ls:..LtPInt l) (hs:..LtPInt h) = flatten (streamDownMk l h) (streamDownStep l h) $ streamDown ls hs {-# Inline streamUp #-} {-# Inline streamDown #-} instance IndexStream z => IndexStream (z:.PInt O p) where streamUp (ls:..LtPInt l) (hs:..LtPInt h) = flatten (streamDownMk l h) (streamDownStep l h) $ streamUp ls hs streamDown (ls:..LtPInt l) (hs:..LtPInt h) = flatten (streamUpMk l h) (streamUpStep l h) $ streamDown ls hs {-# Inline streamUp #-} {-# Inline streamDown #-} instance IndexStream z => IndexStream (z:.PInt C p) where streamUp (ls:..LtPInt l) (hs:..LtPInt h) = flatten (streamUpMk l h) (streamUpStep l h) $ streamUp ls hs streamDown (ls:..LtPInt l) (hs:..LtPInt h) = flatten (streamDownMk l h) (streamDownStep l h) $ streamDown ls hs {-# Inline streamUp #-} {-# Inline streamDown #-} instance IndexStream (Z:.PInt ioc p) => IndexStream (PInt ioc p) where streamUp l h = map (\(Z:.i) -> i) $ streamUp (ZZ:..l) (ZZ:..h) {-# INLINE streamUp #-} streamDown l h = map (\(Z:.i) -> i) $ streamDown (ZZ:..l) (ZZ:..h) {-# INLINE streamDown #-} streamUpMk l h z = return (z,l) {-# Inline [0] streamUpMk #-} streamUpStep l h (z,k) | k > h = return $ Done | otherwise = return $ Yield (z:.PInt k) (z,k+1) {-# Inline [0] streamUpStep #-} streamDownMk l h z = return (z,h) {-# Inline [0] streamDownMk #-} streamDownStep l h (z,k) | k < l = return $ Done | otherwise = return $ Yield (z:.PInt k) (z,k-1) {-# Inline [0] streamDownStep #-}