1{-# OPTIONS_GHC -fno-warn-orphans #-}
3{-# LANGUAGE UnboxedTuples #-}
7-- Module : Streamly.Internal.Data.Array
8-- Copyright : (c) 2019 Composewell Technologies
10-- License : BSD-3-Clause
11-- Maintainer : streamly@composewell.com
12-- Stability : experimental
15module Streamly.Internal.Data.Array
46import Prelude hiding (foldr, length, read)
47#if !MIN_VERSION_primitive(0,7,1)
48import Control.DeepSeq (NFData(..))
50import Control.Monad (when)
51import Control.Monad.IO.Class (liftIO, MonadIO)
52import GHC.IO (unsafePerformIO)
53import GHC.Base (Int(..))
54import Data.Functor.Identity (runIdentity)
55import Data.Primitive.Array hiding (fromList, fromListN)
56import qualified GHC.Exts as Exts
58import Streamly.Internal.Data.Unfold.Types (Unfold(..))
59import Streamly.Internal.Data.Fold.Types (Fold(..))
60import Streamly.Internal.Data.Stream.StreamK.Type (IsStream)
61import Streamly.Internal.Data.Stream.Serial (SerialT)
63import qualified Streamly.Internal.Data.Stream.StreamD as D
65{-# NOINLINE bottomElement #-}
67bottomElement = undefined
69{-# INLINE_NORMAL toStreamD #-}
70toStreamD :: Monad m => Array a -> D.Stream m a
71toStreamD arr = D.Stream step 0
73 {-# INLINE_LATE step #-}
75 | i == length arr = return D.Stop
78 case Exts.indexArray# (array# arr) i of
79 (# x #) -> D.Yield x (I# i + 1)
82length :: Array a -> Int
85{-# INLINE_NORMAL toStreamDRev #-}
86toStreamDRev :: Monad m => Array a -> D.Stream m a
87toStreamDRev arr = D.Stream step (length arr - 1)
89 {-# INLINE_LATE step #-}
91 | i < 0 = return D.Stop
94 case Exts.indexArray# (array# arr) i of
95 (# x #) -> D.Yield x (I# i - 1)
97{-# INLINE_NORMAL foldl' #-}
98foldl' :: (b -> a -> b) -> b -> Array a -> b
99foldl' f z arr = runIdentity $ D.foldl' f z $ toStreamD arr
101{-# INLINE_NORMAL foldr #-}
102foldr :: (a -> b -> b) -> b -> Array a -> b
103foldr f z arr = runIdentity $ D.foldr f z $ toStreamD arr
105-- writeN n = S.evertM (fromStreamDN n)
106{-# INLINE_NORMAL writeN #-}
107writeN :: MonadIO m => Int -> Fold m a (Array a)
108writeN limit = Fold step initial extract
111 marr <- liftIO $ newArray limit bottomElement
114 | i == limit = return (marr, i)
116 liftIO $ writeArray marr i x
118 extract (marr, len) = liftIO $ freezeArray marr 0 len
120{-# INLINE_NORMAL write #-}
121write :: MonadIO m => Fold m a (Array a)
122write = Fold step initial extract
125 marr <- liftIO $ newArray 0 bottomElement
127 step (marr, i, capacity) x
129 let newCapacity = max (capacity * 2) 1
130 in do newMarr <- liftIO $ newArray newCapacity bottomElement
131 liftIO $ copyMutableArray newMarr 0 marr 0 i
132 liftIO $ writeArray newMarr i x
133 return (newMarr, i + 1, newCapacity)
135 liftIO $ writeArray marr i x
136 return (marr, i + 1, capacity)
137 extract (marr, len, _) = liftIO $ freezeArray marr 0 len
139{-# INLINE_NORMAL fromStreamDN #-}
140fromStreamDN :: MonadIO m => Int -> D.Stream m a -> m (Array a)
141fromStreamDN limit str = do
142 marr <- liftIO $ newArray (max limit 0) bottomElement
145 (\i x -> i `seq` liftIO $ writeArray marr i x >> return (i + 1))
148 liftIO $ freezeArray marr 0 i
150{-# INLINE fromStreamD #-}
151fromStreamD :: MonadIO m => D.Stream m a -> m (Array a)
152fromStreamD = D.runFold write
154{-# INLINABLE fromListN #-}
155fromListN :: Int -> [a] -> Array a
156fromListN n xs = unsafePerformIO $ fromStreamDN n $ D.fromList xs
158{-# INLINABLE fromList #-}
159fromList :: [a] -> Array a
160fromList xs = unsafePerformIO $ fromStreamD $ D.fromList xs
162#if !MIN_VERSION_primitive(0,7,1)
163instance NFData a => NFData (Array a) where
165 rnf = foldl' (\_ x -> rnf x) ()
168{-# INLINE fromStreamN #-}
169fromStreamN :: MonadIO m => Int -> SerialT m a -> m (Array a)
171 when (n < 0) $ error "fromStreamN: negative write count specified"
172 fromStreamDN n $ D.toStreamD m
174{-# INLINE fromStream #-}
175fromStream :: MonadIO m => SerialT m a -> m (Array a)
176fromStream m = fromStreamD $ D.toStreamD m
178{-# INLINE_EARLY toStream #-}
179toStream :: (Monad m, IsStream t) => Array a -> t m a
180toStream = D.fromStreamD . toStreamD
182{-# INLINE_EARLY toStreamRev #-}
183toStreamRev :: (Monad m, IsStream t) => Array a -> t m a
184toStreamRev = D.fromStreamD . toStreamDRev
187fold :: Monad m => Fold m a b -> Array a -> m b
188fold f arr = D.runFold f (toStreamD arr)
190{-# INLINE streamFold #-}
191streamFold :: Monad m => (SerialT m a -> m b) -> Array a -> m b
192streamFold f arr = f (toStream arr)
194{-# INLINE_NORMAL read #-}
195read :: Monad m => Unfold m (Array a) a
196read = Unfold step inject
198 inject arr = return (arr, 0)
200 | i == length arr = return D.Stop
203 case Exts.indexArray# (array# arr) i of
204 (# 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