@@ -135,7 +135,7 @@ module Streamly.Internal.Data.Array.Storable.Foreign
135135 , fold
136136
137137 -- * Folds with Array as the container
138− , D.lastN
138+ , lastN
139139 )
140140where
141141
@@ -157,17 +157,21 @@ import GHC.Ptr (Ptr(..))
157157import GHC.Prim (touch#)
158158import GHC.IO (IO(..))
159159
160−import Streamly.Internal.Data.Fold.Types (Fold(..))
161−import Streamly.Internal.Data.Unfold.Types (Unfold(..))
162160import Streamly.Internal.Data.Array.Storable.Foreign.Types (Array(..), length)
161+import Streamly.Internal.Data.Fold.Types (Fold(..))
163162import Streamly.Internal.Data.Stream.Serial (SerialT)
164163import Streamly.Internal.Data.Stream.StreamK.Type (IsStream)
164+import Streamly.Internal.Data.Tuple.Strict (Tuple3'(..))
165+import Streamly.Internal.Data.Unfold.Types (Unfold(..))
165166
167+import qualified Streamly.Internal.Data.Array.Storable.Foreign.Mut.Types as MA
166168import qualified Streamly.Internal.Data.Array.Storable.Foreign.Types as A
169+import qualified Streamly.Internal.Data.Fold as FL
167170import qualified Streamly.Internal.Data.Stream.Prelude as P
168171import qualified Streamly.Internal.Data.Stream.Serial as Serial
169172import qualified Streamly.Internal.Data.Stream.StreamD as D
170173import qualified Streamly.Internal.Data.Stream.StreamK as K
174+import qualified Streamly.Memory.Ring as RB
171175
172176-------------------------------------------------------------------------------
173177-- Construction
@@ -301,6 +305,29 @@ null arr = length arr == 0
301305last :: Storable a => Array a -> Maybe a
302306last arr = readIndex arr (length arr - 1)
303307
308+-------------------------------------------------------------------------------
309+-- Folds with Array as the container
310+-------------------------------------------------------------------------------
311+
312+-- | Take last 'n' elements from the stream and discard the rest.
313+{-# INLINE lastN #-}
314+lastN :: (Storable a, MonadIO m) => Int -> Fold m a (Array a)
315+lastN n
316+ | n <= 0 = fmap (const mempty) FL.drain
317+ | otherwise = A.unsafeFreeze <$> Fold step initial done
318+ where
319+ step (Tuple3' rb rh i) a = do
320+ rh1 <- liftIO $ RB.unsafeInsert rb rh a
321+ return $ FL.Partial $ Tuple3' rb rh1 (i + 1)
322+ initial = fmap (\(a, b) -> Tuple3' a b (0 :: Int)) $ liftIO $ RB.new n
323+ done (Tuple3' rb rh i) = do
324+ arr <- liftIO $ MA.newArray n
325+ foldFunc i rh snoc' arr rb
326+ snoc' b a = liftIO $ MA.unsafeSnoc b a
327+ foldFunc i
328+ | i < n = RB.unsafeFoldRingM
329+ | otherwise = RB.unsafeFoldRingFullM
330+
304331-------------------------------------------------------------------------------
305332-- Random Access
306333-------------------------------------------------------------------------------