1{-# OPTIONS_GHC -fno-warn-orphans #-}
4{-# LANGUAGE MagicHash #-}
5{-# LANGUAGE UnboxedTuples #-}
10-- Module : Streamly.Internal.Data.Array
11-- Copyright : (c) 2019 Composewell Technologies
13-- License : BSD-3-Clause
14-- Maintainer : streamly@composewell.com
15-- Stability : experimental
18module Streamly.Internal.Data.Array
49import Prelude hiding (foldr, length, read)
50import Control.DeepSeq (NFData(..))
51import Control.Monad (when)
52import Control.Monad.IO.Class (liftIO, MonadIO)
53import GHC.IO (unsafePerformIO)
54import GHC.Base (Int(..))
55import Data.Functor.Identity (runIdentity)
56import Data.Primitive.Array hiding (fromList, fromListN)
57import qualified GHC.Exts as Exts
59import Streamly.Internal.Data.Unfold.Types (Unfold(..))
60import Streamly.Internal.Data.Fold.Types (Fold(..))
61import Streamly.Internal.Data.Stream.StreamK.Type (IsStream)
62import Streamly.Internal.Data.Stream.Serial (SerialT)
64import qualified Streamly.Internal.Data.Stream.StreamD as D
66{-# NOINLINE bottomElement #-}
68bottomElement = undefined
70{-# INLINE_NORMAL toStreamD #-}
71toStreamD :: Monad m => Array a -> D.Stream m a
72toStreamD arr = D.Stream step 0
74 {-# INLINE_LATE step #-}
76 | i == length arr = return D.Stop
79 case Exts.indexArray# (array# arr) i of
80 (# x #) -> D.Yield x (I# i + 1)
83length :: Array a -> Int
86{-# INLINE_NORMAL toStreamDRev #-}
87toStreamDRev :: Monad m => Array a -> D.Stream m a
88toStreamDRev arr = D.Stream step (length arr - 1)
90 {-# INLINE_LATE step #-}
92 | i < 0 = return D.Stop
95 case Exts.indexArray# (array# arr) i of
96 (# x #) -> D.Yield x (I# i - 1)
98{-# INLINE_NORMAL foldl' #-}
99foldl' :: (b -> a -> b) -> b -> Array a -> b
100foldl' f z arr = runIdentity $ D.foldl' f z $ toStreamD arr
102{-# INLINE_NORMAL foldr #-}
103foldr :: (a -> b -> b) -> b -> Array a -> b
104foldr f z arr = runIdentity $ D.foldr f z $ toStreamD arr
106-- writeN n = S.evertM (fromStreamDN n)
107{-# INLINE_NORMAL writeN #-}
108writeN :: MonadIO m => Int -> Fold m a (Array a)
109writeN limit = Fold step initial extract
112 marr <- liftIO $ newArray limit bottomElement
115 | i == limit = return (marr, i)
117 liftIO $ writeArray marr i x
119 extract (marr, len) = liftIO $ freezeArray marr 0 len
121{-# INLINE_NORMAL write #-}
122write :: MonadIO m => Fold m a (Array a)
123write = Fold step initial extract
126 marr <- liftIO $ newArray 0 bottomElement
128 step (marr, i, capacity) x
130 let newCapacity = max (capacity * 2) 1
131 in do newMarr <- liftIO $ newArray newCapacity bottomElement
132 liftIO $ copyMutableArray newMarr 0 marr 0 i
133 liftIO $ writeArray newMarr i x
134 return (newMarr, i + 1, newCapacity)
136 liftIO $ writeArray marr i x
137 return (marr, i + 1, capacity)
138 extract (marr, len, _) = liftIO $ freezeArray marr 0 len
140{-# INLINE_NORMAL fromStreamDN #-}
141fromStreamDN :: MonadIO m => Int -> D.Stream m a -> m (Array a)
142fromStreamDN limit str = do
143 marr <- liftIO $ newArray (max limit 0) bottomElement
146 (\i x -> i `seq` liftIO $ writeArray marr i x >> return (i + 1))
149 liftIO $ freezeArray marr 0 i
151{-# INLINE fromStreamD #-}
152fromStreamD :: MonadIO m => D.Stream m a -> m (Array a)
153fromStreamD = D.runFold write
155{-# INLINABLE fromListN #-}
156fromListN :: Int -> [a] -> Array a
157fromListN n xs = unsafePerformIO $ fromStreamDN n $ D.fromList xs
159{-# INLINABLE fromList #-}
160fromList :: [a] -> Array a
161fromList xs = unsafePerformIO $ fromStreamD $ D.fromList xs
163instance NFData a => NFData (Array a) where
165 rnf = foldl' (\_ x -> rnf x) ()
167{-# INLINE fromStreamN #-}
168fromStreamN :: MonadIO m => Int -> SerialT m a -> m (Array a)
170 when (n < 0) $ error "fromStreamN: negative write count specified"
171 fromStreamDN n $ D.toStreamD m
173{-# INLINE fromStream #-}
174fromStream :: MonadIO m => SerialT m a -> m (Array a)
175fromStream m = fromStreamD $ D.toStreamD m
177{-# INLINE_EARLY toStream #-}
178toStream :: (Monad m, IsStream t) => Array a -> t m a
179toStream = D.fromStreamD . toStreamD
181{-# INLINE_EARLY toStreamRev #-}
182toStreamRev :: (Monad m, IsStream t) => Array a -> t m a
183toStreamRev = D.fromStreamD . toStreamDRev
186fold :: Monad m => Fold m a b -> Array a -> m b
187fold f arr = D.runFold f (toStreamD arr)
189{-# INLINE streamFold #-}
190streamFold :: Monad m => (SerialT m a -> m b) -> Array a -> m b
191streamFold f arr = f (toStream arr)
193{-# INLINE_NORMAL read #-}
194read :: Monad m => Unfold m (Array a) a
195read = Unfold step inject
197 inject arr = return (arr, 0)
199 | i == length arr = return D.Stop
202 case Exts.indexArray# (array# arr) i of
203 (# x #) -> D.Yield x (arr, I# 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