1{-# OPTIONS_GHC -fno-warn-orphans #-}
8-- Module : Streamly.Internal.Data.Prim.Array
9-- Copyright : (c) 2019 Composewell Technologies
11-- License : BSD-3-Clause
12-- Maintainer : streamly@composewell.com
13-- Stability : experimental
16module Streamly.Internal.Data.Prim.Array
19 -- XXX should it be just Array instead? We should be able to replace one
20 -- array type with another easily.
23 -- XXX Prim should be exported from Data.Prim module?
55import Prelude hiding (foldr, length, read)
56import Control.DeepSeq (NFData(..))
57import Control.Monad (when)
58import Control.Monad.IO.Class (liftIO, MonadIO)
59import GHC.IO (unsafePerformIO)
60import Data.Primitive.Types (Prim(..))
62import Streamly.Internal.Data.Prim.Array.Types
63import Streamly.Internal.Data.Unfold.Types (Unfold(..))
64import Streamly.Internal.Data.Fold.Types (Fold(..))
65import Streamly.Internal.Data.Stream.StreamK.Type (IsStream)
66import Streamly.Internal.Data.Stream.Serial (SerialT)
68import qualified Streamly.Internal.Data.Stream.StreamD as D
70{-# INLINE_NORMAL toStreamD #-}
71toStreamD :: (Prim a, Monad m) => PrimArray a -> D.Stream m a
72toStreamD arr = D.Stream step 0
74 {-# INLINE_LATE step #-}
76 | i == sizeofPrimArray arr = return D.Stop
77 step _ i = return $ D.Yield (indexPrimArray arr i) (i + 1)
80length :: Prim a => PrimArray a -> Int
81length = sizeofPrimArray
83{-# INLINE_NORMAL toStreamDRev #-}
84toStreamDRev :: (Prim a, Monad m) => PrimArray a -> D.Stream m a
85toStreamDRev arr = D.Stream step (sizeofPrimArray arr - 1)
87 {-# INLINE_LATE step #-}
89 | i < 0 = return D.Stop
90 step _ i = return $ D.Yield (indexPrimArray arr i) (i - 1)
92{-# INLINE_NORMAL foldl' #-}
93foldl' :: Prim a => (b -> a -> b) -> b -> PrimArray a -> b
94foldl' = foldlPrimArray'
96{-# INLINE_NORMAL foldr #-}
97foldr :: Prim a => (a -> b -> b) -> b -> PrimArray a -> b
100-- writeN n = S.evertM (fromStreamDN n)
101{-# INLINE_NORMAL writeN #-}
102writeN :: (MonadIO m, Prim a) => Int -> Fold m a (PrimArray a)
103writeN limit = Fold step initial extract
106 marr <- liftIO $ newPrimArray limit
109 | i == limit = return (marr, i)
111 liftIO $ writePrimArray marr i x
113 extract (marr, _) = liftIO $ unsafeFreezePrimArray marr
115{-# INLINE_NORMAL write #-}
116write :: (MonadIO m, Prim a) => Fold m a (PrimArray a)
117write = Fold step initial extract
120 marr <- liftIO $ newPrimArray 0
122 step (marr, i, capacity) x
124 let newCapacity = max (capacity * 2) 1
125 in do newMarr <- liftIO $ resizeMutablePrimArray marr newCapacity
126 liftIO $ writePrimArray newMarr i x
127 return (newMarr, i + 1, newCapacity)
129 liftIO $ writePrimArray marr i x
130 return (marr, i + 1, capacity)
131 extract (marr, len, _) = do liftIO $ shrinkMutablePrimArray marr len
132 liftIO $ unsafeFreezePrimArray marr
134{-# INLINE_NORMAL fromStreamDN #-}
135fromStreamDN :: (MonadIO m, Prim a) => Int -> D.Stream m a -> m (PrimArray a)
136fromStreamDN limit str = do
137 marr <- liftIO $ newPrimArray (max limit 0)
140 (\i x -> i `seq` liftIO (writePrimArray marr i x) >> return (i + 1))
143 liftIO $ unsafeFreezePrimArray marr
145{-# INLINE fromStreamD #-}
146fromStreamD :: (MonadIO m, Prim a) => D.Stream m a -> m (PrimArray a)
147fromStreamD = D.runFold write
149{-# INLINABLE fromListN #-}
150fromListN :: Prim a => Int -> [a] -> PrimArray a
151fromListN n xs = unsafePerformIO $ fromStreamDN n $ D.fromList xs
153{-# INLINABLE fromList #-}
154fromList :: Prim a => [a] -> PrimArray a
155fromList xs = unsafePerformIO $ fromStreamD $ D.fromList xs
157instance Prim a => NFData (PrimArray a) where
159 rnf = foldl' (\_ _ -> ()) ()
161{-# INLINE fromStreamN #-}
162fromStreamN :: (MonadIO m, Prim a) => Int -> SerialT m a -> m (PrimArray a)
164 when (n < 0) $ error "fromStreamN: negative write count specified"
165 fromStreamDN n $ D.toStreamD m
167{-# INLINE fromStream #-}
168fromStream :: (MonadIO m, Prim a) => SerialT m a -> m (PrimArray a)
169fromStream m = fromStreamD $ D.toStreamD m
171{-# INLINE_EARLY toStream #-}
172toStream :: (Prim a, Monad m, IsStream t) => PrimArray a -> t m a
173toStream = D.fromStreamD . toStreamD
175{-# INLINE_EARLY toStreamRev #-}
176toStreamRev :: (Prim a, Monad m, IsStream t) => PrimArray a -> t m a
177toStreamRev = D.fromStreamD . toStreamDRev
180fold :: (Prim a, Monad m) => Fold m a b -> PrimArray a -> m b
181fold f arr = D.runFold f (toStreamD arr)
183{-# INLINE streamFold #-}
184streamFold :: (Prim a, Monad m) => (SerialT m a -> m b) -> PrimArray a -> m b
185streamFold f arr = f (toStream arr)
187{-# INLINE_NORMAL read #-}
188read :: (Prim a, Monad m) => Unfold m (PrimArray a) a
189read = Unfold step inject
191 inject arr = return (arr, 0)
193 | i == length arr = return D.Stop
194 step (arr, i) = return $ D.Yield (indexPrimArray arr i) (arr, i + 1)
196{-# INLINE_NORMAL readSlice #-}
197readSlice :: (Prim a, Monad m) => Int -> Int -> Unfold m (PrimArray a) a
198readSlice off len = Unfold step inject
200 inject arr = return (arr, off)
202 | i == min (off + len) (length arr) = return D.Stop
203 step (arr, i) = return $ D.Yield (indexPrimArray arr i) (arr, i + 1)
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list