massiv-1.0.2.0: src/Data/Massiv/Vector/Stream.hs
{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE CPP #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TupleSections #-}
{-# LANGUAGE TypeFamilies #-}
{-# OPTIONS_GHC -fno-warn-orphans #-}
{-# OPTIONS_HADDOCK hide, not-home #-}
-- |
-- Module : Data.Massiv.Vector.Stream
-- Copyright : (c) Alexey Kuleshevich 2019-2022
-- License : BSD3
-- Maintainer : Alexey Kuleshevich <lehins@yandex.ru>
-- Stability : experimental
-- Portability : non-portable
--
module Data.Massiv.Vector.Stream
( -- | This module has a similar purpose as the 'Data.Vector.Fusion.Bundle.Monadic', but
-- quite a bit simpler.
--
-- __Important__ - This module is still experimental, as such it is considered
-- internal and exported for the curious users only.
Steps(..)
, Stream(..)
-- * Conversion
, steps
, isteps
, consume
, fromStream
, fromStreamM
, fromStreamExactM
, unstreamExact
, unstreamMax
, unstreamMaxM
, unstreamUnknown
, unstreamUnknownM
, unstreamIntoM
-- * Bundle
, toBundle
, fromBundle
, fromBundleM
-- * Operations on Steps
, length
, null
, empty
, singleton
, generate
, headMaybe
, last
, cons
, uncons
, snoc
, drop
, take
, slice
, iterateN
, iterateNM
, replicate
, replicateM
, generateM
, traverse
, map
, mapM
, mapM_
, indexed
, concatMap
, append
, zipWith
, zipWith3
, zipWith4
, zipWith5
, zipWith6
, zipWithM
, zipWith3M
, zipWith4M
, zipWith5M
, zipWith6M
, zipWithM_
, zipWith3M_
, zipWith4M_
, zipWith5M_
, zipWith6M_
-- ** Folding
, foldl
, foldl1
, foldlM
, foldl1M
, foldlLazy
, foldl1Lazy
, foldlLazyM
, foldl1LazyM
, foldrLazy
, foldr1Lazy
, foldrLazyM
, foldr1LazyM
, or
, and
-- ** Unfolding
, unfoldr
, unfoldrN
, unsafeUnfoldrN
, unfoldrM
, unfoldrNM
, unsafeUnfoldrNM
, unfoldrExactN
, unfoldrExactNM
-- ** Enumeration
, enumFromStepN
-- * Lists
, toList
, fromList
, fromListN
, unsafeFromListN
-- ** Filter
, mapMaybe
, mapMaybeA
, mapMaybeM
, filter
, filterA
, filterM
-- * Transformations
, transSteps
, transStepsId
-- * Useful re-exports
, module Data.Vector.Fusion.Util
, Id(..)
) where
import qualified Control.Monad as M
import Control.Monad.ST
import qualified Data.Foldable as F
import Data.Massiv.Core.Common hiding (empty, singleton, replicate)
import Data.Coerce
import Data.Maybe (catMaybes)
import qualified Data.Traversable as Traversable (traverse)
import qualified Data.Vector.Fusion.Bundle.Monadic as B
import qualified Data.Vector.Fusion.Bundle.Size as B
import qualified Data.Vector.Fusion.Stream.Monadic as S
import Data.Vector.Fusion.Util
import Prelude hiding (and, concatMap, drop, filter, foldl, foldl1, foldr,
foldr1, length, map, mapM, mapM_, null, or, replicate, take,
traverse, zipWith, zipWith3)
import qualified GHC.Exts (IsList(..))
instance Monad m => Functor (Steps m) where
fmap f str = str {stepsStream = S.map f (stepsStream str)}
{-# INLINE fmap #-}
(<$) e str =
case stepsSize str of
LengthExact n -> str {stepsStream = S.replicate (coerce n) e}
_ -> fmap (const e) str
{-# INLINE (<$) #-}
instance Monad m => Semigroup (Steps m e) where
(<>) = append
{-# INLINE (<>) #-}
instance Monad m => Monoid (Steps m e) where
mempty = empty
{-# INLINE mempty #-}
#if !MIN_VERSION_base(4,11,0)
mappend = append
{-# INLINE mappend #-}
#endif
instance GHC.Exts.IsList (Steps Id e) where
type Item (Steps Id e) = e
toList = toList
{-# INLINE toList #-}
fromList = fromList
{-# INLINE fromList #-}
fromListN n = (`Steps` LengthMax (Sz n)) . S.fromListN n
{-# INLINE fromListN #-}
instance Foldable (Steps Id) where
foldr f acc = unId . foldrLazy f acc
{-# INLINE foldr #-}
foldl f acc = unId . foldlLazy f acc
{-# INLINE foldl #-}
foldl' f acc = unId . foldl f acc
{-# INLINE foldl' #-}
foldr1 f = unId . foldr1Lazy f
{-# INLINE foldr1 #-}
foldl1 f = unId . foldl1Lazy f
{-# INLINE foldl1 #-}
toList = toList
{-# INLINE toList #-}
length = unId . length
{-# INLINE length #-}
null = unId . null
{-# INLINE null #-}
sum = unId . foldl (+) 0
{-# INLINE sum #-}
product = unId . foldl (*) 1
{-# INLINE product #-}
maximum = unId . foldl1 max
{-# INLINE maximum #-}
minimum = unId . foldl1 min
{-# INLINE minimum #-}
steps :: forall r ix e m . (Monad m, Index ix, Source r e) => Array r ix e -> Steps m e
steps !arr =
case unsafePrefIndex arr of
PrefIndex gix -> gix <$> ixRangeSteps (size arr)
PrefIndexLinear gi ->
Steps (S.Stream step 0) (LengthExact (coerce k))
where
k = totalElem $ size arr
step i
| i < k =
let e = gi i
in e `seq` pure $ S.Yield e (i + 1)
| otherwise = pure S.Done
{-# INLINE [0] step #-}
{-# INLINE [1] steps #-}
ixRangeSteps :: forall ix m . (Monad m, Index ix) => Sz ix -> Steps m ix
ixRangeSteps sz = Steps (S.Stream step initStep) (LengthExact k)
where
!k = toLinearSz sz
!initStep = if k == zeroSz then Nothing else Just zeroIndex
step (Just ix) = stepNextMF ix (unSz sz) oneIndex (<) $ \ mIx -> pure $ S.Yield ix mIx
step Nothing = pure S.Done
{-# INLINE [0] step #-}
{-# INLINE [1] ixRangeSteps #-}
isteps :: forall r ix e m . (Monad m, Index ix, Source r e) => Array r ix e -> Steps m (ix, e)
isteps !arr =
case unsafePrefIndex arr of
PrefIndex gix -> (\ !ix -> let e = gix ix in e `seq` (ix, e)) <$> ixRangeSteps sz
PrefIndexLinear gi ->
let k = totalElem sz
step i
| i < k =
let e = gi i
in e `seq` pure $ S.Yield (fromLinearIndex sz i, e) (i + 1)
| otherwise = pure S.Done
{-# INLINE [0] step #-}
in Steps (S.Stream step 0) (LengthExact (coerce k))
where
!sz = size arr
{-# INLINE isteps #-}
toBundle :: (Monad m, Index ix, Source r e) => Array r ix e -> B.Bundle m v e
toBundle arr =
let Steps str k = steps arr
in B.fromStream str (sizeHintToBundleSize k)
{-# INLINE toBundle #-}
fromBundle :: Manifest r e => B.Bundle Id v e -> Vector r e
fromBundle bundle = fromStream (B.sSize bundle) (B.sElems bundle)
{-# INLINE fromBundle #-}
fromBundleM :: (Monad m, Manifest r e) => B.Bundle m v e -> m (Vector r e)
fromBundleM bundle = fromStreamM (B.sSize bundle) (B.sElems bundle)
{-# INLINE fromBundleM #-}
fromStream :: forall r e . Manifest r e => B.Size -> S.Stream Id e -> Vector r e
fromStream sz str =
case B.upperBound sz of
Nothing -> unstreamUnknown str
Just k -> unstreamMax k str
{-# INLINE fromStream #-}
fromStreamM :: forall r e m. (Monad m, Manifest r e) => B.Size -> S.Stream m e -> m (Vector r e)
fromStreamM sz str = do
xs <- S.toList str
case B.upperBound sz of
Nothing -> pure $! unstreamUnknown (S.fromList xs)
Just k -> pure $! unstreamMax k (S.fromList xs)
{-# INLINE fromStreamM #-}
fromStreamExactM ::
forall r ix e m. (Monad m, Manifest r e, Index ix)
=> Sz ix
-> S.Stream m e
-> m (Array r ix e)
fromStreamExactM sz str = do
xs <- S.toList str
pure $! unstreamExact sz (S.fromList xs)
{-# INLINE fromStreamExactM #-}
unstreamIntoM ::
(Manifest r a, PrimMonad m)
=> MVector (PrimState m) r a
-> LengthHint
-> S.Stream Id a
-> m (MVector (PrimState m) r a)
unstreamIntoM marr sz str =
case sz of
LengthExact _ -> marr <$ unstreamMaxM marr str
LengthMax _ -> unsafeLinearShrink marr . SafeSz =<< unstreamMaxM marr str
LengthUnknown -> unstreamUnknownM marr str
{-# INLINE unstreamIntoM #-}
unstreamMax ::
forall r e. (Manifest r e)
=> Int
-> S.Stream Id e
-> Vector r e
unstreamMax kMax str =
runST $ do
marr <- unsafeNew (SafeSz kMax)
k <- unstreamMaxM marr str
unsafeLinearShrink marr (SafeSz k) >>= unsafeFreeze Seq
{-# INLINE unstreamMax #-}
unstreamMaxM ::
(Manifest r a, Index ix, PrimMonad m) => MArray (PrimState m) r ix a -> S.Stream Id a -> m Int
unstreamMaxM marr (S.Stream step s) = stepLoad s 0
where
stepLoad t i =
case unId (step t) of
S.Yield e' t' -> do
unsafeLinearWrite marr i e'
stepLoad t' (i + 1)
S.Skip t' -> stepLoad t' i
S.Done -> pure i
{-# INLINE stepLoad #-}
{-# INLINE unstreamMaxM #-}
unstreamUnknown :: Manifest r a => S.Stream Id a -> Vector r a
unstreamUnknown str =
runST $ do
marr <- unsafeNew zeroSz
unstreamUnknownM marr str >>= unsafeFreeze Seq
{-# INLINE unstreamUnknown #-}
unstreamUnknownM ::
(Manifest r a, PrimMonad m)
=> MVector (PrimState m) r a
-> S.Stream Id a
-> m (MVector (PrimState m) r a)
unstreamUnknownM marrInit (S.Stream step s) = stepLoad s 0 (unSz (sizeOfMArray marrInit)) marrInit
where
stepLoad t i kMax marr
| i < kMax =
case unId (step t) of
S.Yield e' t' -> do
unsafeLinearWrite marr i e'
stepLoad t' (i + 1) kMax marr
S.Skip t' -> stepLoad t' i kMax marr
S.Done -> unsafeLinearShrink marr (SafeSz i)
| otherwise = do
let kMax' = max 1 (kMax * 2)
marr' <- unsafeLinearGrow marr (SafeSz kMax')
stepLoad t i kMax' marr'
{-# INLINE stepLoad #-}
{-# INLINE unstreamUnknownM #-}
unstreamExact ::
forall r ix e. (Manifest r e, Index ix)
=> Sz ix
-> S.Stream Id e
-> Array r ix e
unstreamExact sz str =
runST $ do
marr <- unsafeNew sz
_ <- unstreamMaxM marr str
unsafeFreeze Seq marr
{-# INLINE unstreamExact #-}
length :: Monad m => Steps m a -> m Int
length (Steps str sz) =
case sz of
LengthExact k -> pure $ coerce k
_ -> S.length str
{-# INLINE length #-}
null :: Monad m => Steps m a -> m Bool
null (Steps str sz) =
case sz of
LengthExact k -> pure (k == zeroSz)
_ -> S.null str
{-# INLINE null #-}
empty :: Monad m => Steps m e
empty = Steps S.empty (LengthExact zeroSz)
{-# INLINE empty #-}
singleton :: Monad m => e -> Steps m e
singleton e = Steps (S.singleton e) (LengthExact oneSz)
{-# INLINE singleton #-}
generate :: Monad m => Sz1 -> (Int -> e) -> Steps m e
generate k f = Steps (S.generate (coerce k) f) (LengthExact k)
{-# INLINE generate #-}
-- | First element of the 'Stream' or error if empty
headMaybe :: Monad m => Steps m a -> m (Maybe a)
headMaybe (Steps (S.Stream step t) _) = headMaybeLoop S.SPEC t
where
headMaybeLoop !_ s = do
r <- step s
case r of
S.Yield x _ -> pure $ Just x
S.Skip s' -> headMaybeLoop S.SPEC s'
S.Done -> pure Nothing
{-# INLINE [0] headMaybeLoop #-}
{-# INLINE headMaybe #-}
cons :: Monad m => e -> Steps m e -> Steps m e
cons e (Steps str k) = Steps (S.cons e str) (k `addInt` 1)
{-# INLINE cons #-}
-- | First element of the `Steps` or `Nothing` if empty
uncons :: Monad m => Steps m e -> m (Maybe (e, Steps m e))
uncons sts = (\mx -> (, drop oneSz sts) <$> mx) <$> headMaybe sts
{-# INLINE uncons #-}
snoc :: Monad m => Steps m e -> e -> Steps m e
snoc (Steps str k) e = Steps (S.snoc str e) (k `addInt` 1)
{-# INLINE snoc #-}
traverse :: (Monad m, Applicative f) => (e -> f a) -> Steps Id e -> f (Steps m a)
traverse f (Steps str k) = (`Steps` k) <$> liftListA (Traversable.traverse f) str
{-# INLINE traverse #-}
append :: Monad m => Steps m e -> Steps m e -> Steps m e
append (Steps str1 k1) (Steps str2 k2) = Steps (str1 S.++ str2) (k1 `addLengthHint` k2)
{-# INLINE append #-}
map :: Monad m => (e -> a) -> Steps m e -> Steps m a
map f (Steps str k) = Steps (S.map f str) k
{-# INLINE map #-}
indexed :: Monad m => Steps m e -> Steps m (Int, e)
indexed (Steps str k) = Steps (S.indexed str) k
{-# INLINE indexed #-}
mapM :: Monad m => (e -> m a) -> Steps m e -> Steps m a
mapM f (Steps str k) = Steps (S.mapM f str) k
{-# INLINE mapM #-}
mapM_ :: Monad m => (e -> m a) -> Steps m e -> m ()
mapM_ f (Steps str _) = S.mapM_ f str
{-# INLINE mapM_ #-}
zipWith :: Monad m => (a -> b -> e) -> Steps m a -> Steps m b -> Steps m e
zipWith f (Steps sa ka) (Steps sb kb) = Steps (S.zipWith f sa sb) (minLengthHint ka kb)
{-# INLINE zipWith #-}
zipWith3 :: Monad m => (a -> b -> c -> d) -> Steps m a -> Steps m b -> Steps m c -> Steps m d
zipWith3 f (Steps sa ka) (Steps sb kb) (Steps sc kc) =
Steps (S.zipWith3 f sa sb sc) (minLengthHint ka (minLengthHint kb kc))
{-# INLINE zipWith3 #-}
zipWith4 ::
Monad m => (a -> b -> c -> d -> e) -> Steps m a -> Steps m b -> Steps m c -> Steps m d -> Steps m e
zipWith4 f (Steps sa ka) (Steps sb kb) (Steps sc kc) (Steps sd kd) =
Steps (S.zipWith4 f sa sb sc sd) (minLengthHint ka (minLengthHint kb (minLengthHint kc kd)))
{-# INLINE zipWith4 #-}
zipWith5 ::
Monad m
=> (a -> b -> c -> d -> e -> f)
-> Steps m a
-> Steps m b
-> Steps m c
-> Steps m d
-> Steps m e
-> Steps m f
zipWith5 f (Steps sa ka) (Steps sb kb) (Steps sc kc) (Steps sd kd) (Steps se ke) =
Steps (S.zipWith5 f sa sb sc sd se) (minLengthHint ka (minLengthHint kb (minLengthHint kc (minLengthHint kd ke))))
{-# INLINE zipWith5 #-}
zipWith6 ::
Monad m
=> (a -> b -> c -> d -> e -> f -> g)
-> Steps m a
-> Steps m b
-> Steps m c
-> Steps m d
-> Steps m e
-> Steps m f
-> Steps m g
zipWith6 f (Steps sa ka) (Steps sb kb) (Steps sc kc) (Steps sd kd) (Steps se ke) (Steps sf kf) =
Steps
(S.zipWith6 f sa sb sc sd se sf)
(minLengthHint ka (minLengthHint kb (minLengthHint kc (minLengthHint kd (minLengthHint ke kf)))))
{-# INLINE zipWith6 #-}
zipWithM :: Monad m => (a -> b -> m c) -> Steps m a -> Steps m b -> Steps m c
zipWithM f (Steps sa ka) (Steps sb kb) = Steps (S.zipWithM f sa sb) (minLengthHint ka kb)
{-# INLINE zipWithM #-}
zipWith3M :: Monad m => (a -> b -> c -> m d) -> Steps m a -> Steps m b -> Steps m c -> Steps m d
zipWith3M f (Steps sa ka) (Steps sb kb) (Steps sc kc) =
Steps (S.zipWith3M f sa sb sc) (minLengthHint ka (minLengthHint kb kc))
{-# INLINE zipWith3M #-}
zipWith4M ::
Monad m
=> (a -> b -> c -> d -> m e)
-> Steps m a
-> Steps m b
-> Steps m c
-> Steps m d
-> Steps m e
zipWith4M f (Steps sa ka) (Steps sb kb) (Steps sc kc) (Steps sd kd) =
Steps (S.zipWith4M f sa sb sc sd) (minLengthHint ka (minLengthHint kb (minLengthHint kc kd)))
{-# INLINE zipWith4M #-}
zipWith5M ::
Monad m
=> (a -> b -> c -> d -> e -> m f)
-> Steps m a
-> Steps m b
-> Steps m c
-> Steps m d
-> Steps m e
-> Steps m f
zipWith5M f (Steps sa ka) (Steps sb kb) (Steps sc kc) (Steps sd kd) (Steps se ke) =
Steps (S.zipWith5M f sa sb sc sd se) (minLengthHint ka (minLengthHint kb (minLengthHint kc (minLengthHint kd ke))))
{-# INLINE zipWith5M #-}
zipWith6M ::
Monad m
=> (a -> b -> c -> d -> e -> f -> m g)
-> Steps m a
-> Steps m b
-> Steps m c
-> Steps m d
-> Steps m e
-> Steps m f
-> Steps m g
zipWith6M f (Steps sa ka) (Steps sb kb) (Steps sc kc) (Steps sd kd) (Steps se ke) (Steps sf kf) =
Steps
(S.zipWith6M f sa sb sc sd se sf)
(minLengthHint ka (minLengthHint kb (minLengthHint kc (minLengthHint kd (minLengthHint ke kf)))))
{-# INLINE zipWith6M #-}
zipWithM_ :: Monad m => (a -> b -> m c) -> Steps m a -> Steps m b -> m ()
zipWithM_ f (Steps str1 _) (Steps str2 _) = S.zipWithM_ f str1 str2
{-# INLINE zipWithM_ #-}
zipWith3M_ :: Monad m => (a -> b -> c -> m d) -> Steps m a -> Steps m b -> Steps m c -> m ()
zipWith3M_ f sa sb sc = consume $ zipWith3M f sa sb sc
{-# INLINE zipWith3M_ #-}
zipWith4M_ ::
Monad m
=> (a -> b -> c -> d -> m e)
-> Steps m a
-> Steps m b
-> Steps m c
-> Steps m d
-> m ()
zipWith4M_ f sa sb sc sd = consume $ zipWith4M f sa sb sc sd
{-# INLINE zipWith4M_ #-}
zipWith5M_ ::
Monad m
=> (a -> b -> c -> d -> e -> m f)
-> Steps m a
-> Steps m b
-> Steps m c
-> Steps m d
-> Steps m e
-> m ()
zipWith5M_ f sa sb sc sd se = consume $ zipWith5M f sa sb sc sd se
{-# INLINE zipWith5M_ #-}
zipWith6M_ ::
Monad m
=> (a -> b -> c -> d -> e -> f -> m g)
-> Steps m a
-> Steps m b
-> Steps m c
-> Steps m d
-> Steps m e
-> Steps m f
-> m ()
zipWith6M_ f sa sb sc sd se sf = consume $ zipWith6M f sa sb sc sd se sf
{-# INLINE zipWith6M_ #-}
consume :: Monad m => Steps m a -> m ()
consume (Steps (S.Stream step t) _) = consumeLoop S.SPEC t
where
consumeLoop !_ s = do
r <- step s
case r of
S.Yield _ s' -> consumeLoop S.SPEC s'
S.Skip s' -> consumeLoop S.SPEC s'
S.Done -> pure ()
{-# INLINE consume #-}
transStepsId :: Monad m => Steps Id e -> Steps m e
transStepsId (Steps sts k) = Steps (S.trans (pure . unId) sts) k
{-# INLINE transStepsId #-}
transSteps :: (Monad m, Monad n) => Steps m e -> m (Steps n e)
transSteps (Steps strM sz@(LengthExact _)) = (`Steps` sz) <$> transListM strM
transSteps (Steps strM _) = do
(n, strN) <- transListNM strM
pure (Steps strN (LengthExact n))
{-# INLINE transSteps #-}
foldl :: Monad m => (b -> a -> b) -> b -> Steps m a -> m b
foldl f acc = S.foldl' f acc . stepsStream
{-# INLINE foldl #-}
foldl1 :: Monad m => (a -> a -> a) -> Steps m a -> m a
foldl1 f = S.foldl1' f . stepsStream
{-# INLINE foldl1 #-}
foldlM :: Monad m => (a -> b -> m a) -> a -> Steps m b -> m a
foldlM f acc = S.foldlM' f acc . stepsStream
{-# INLINE foldlM #-}
foldl1M :: Monad m => (a -> a -> m a) -> Steps m a -> m a
foldl1M f (Steps sts _) = S.foldl1M' f sts
{-# INLINE foldl1M #-}
foldrLazy :: Monad m => (a -> b -> b) -> b -> Steps m a -> m b
foldrLazy f acc = S.foldr f acc . stepsStream
{-# INLINE foldrLazy #-}
foldr1Lazy :: Monad m => (a -> a -> a) -> Steps m a -> m a
foldr1Lazy f = S.foldr1 f . stepsStream
{-# INLINE foldr1Lazy #-}
foldlLazy :: Monad m => (b -> a -> b) -> b -> Steps m a -> m b
foldlLazy f acc = S.foldl f acc . stepsStream
{-# INLINE foldlLazy #-}
foldl1Lazy :: Monad m => (a -> a -> a) -> Steps m a -> m a
foldl1Lazy f = S.foldl1 f . stepsStream
{-# INLINE foldl1Lazy #-}
foldlLazyM :: Monad m => (a -> b -> m a) -> a -> Steps m b -> m a
foldlLazyM f acc = S.foldlM f acc . stepsStream
{-# INLINE foldlLazyM #-}
foldl1LazyM :: Monad m => (a -> a -> m a) -> Steps m a -> m a
foldl1LazyM f (Steps sts _) = S.foldl1M f sts
{-# INLINE foldl1LazyM #-}
foldrLazyM :: Monad m => (b -> a -> m a) -> a -> Steps m b -> m a
foldrLazyM f acc (Steps sts _) = S.foldrM f acc sts
{-# INLINE foldrLazyM #-}
foldr1LazyM :: Monad m => (a -> a -> m a) -> Steps m a -> m a
foldr1LazyM f = S.foldr1M f . stepsStream
{-# INLINE foldr1LazyM #-}
or :: Monad m => Steps m Bool -> m Bool
or = S.or . stepsStream
{-# INLINE or #-}
and :: Monad m => Steps m Bool -> m Bool
and = S.and . stepsStream
{-# INLINE and #-}
mapMaybe :: Monad m => (a -> Maybe e) -> Steps m a -> Steps m e
mapMaybe f (Steps str k) = Steps (S.mapMaybe f str) (toLengthMax k)
{-# INLINE mapMaybe #-}
concatMap :: Monad m => (a -> Steps m e) -> Steps m a -> Steps m e
concatMap f (Steps str _) = Steps (S.concatMap (stepsStream . f) str) LengthUnknown
{-# INLINE concatMap #-}
mapMaybeA :: (Monad m, Applicative f) => (a -> f (Maybe e)) -> Steps Id a -> f (Steps m e)
mapMaybeA f (Steps str k) = (`Steps` toLengthMax k) <$> liftListA (mapMaybeListA f) str
{-# INLINE mapMaybeA #-}
mapMaybeM :: Monad m => (a -> m (Maybe b)) -> Steps m a -> Steps m b
mapMaybeM f (Steps str k) = Steps (mapMaybeStreamM f str) (toLengthMax k)
{-# INLINE mapMaybeM #-}
mapMaybeListA :: Applicative f => (a -> f (Maybe b)) -> [a] -> f [b]
mapMaybeListA f = fmap catMaybes . Traversable.traverse f
{-# INLINE mapMaybeListA #-}
mapMaybeStreamM :: Monad m => (a -> m (Maybe b)) -> S.Stream m a -> S.Stream m b
mapMaybeStreamM f (S.Stream step t) = S.Stream step' t
where
step' s = do
r <- step s
case r of
S.Yield x s' -> do
b <- f x
pure $
case b of
Nothing -> S.Skip s'
Just b' -> S.Yield b' s'
S.Skip s' -> pure $ S.Skip s'
S.Done -> pure S.Done
{-# INLINE [0] step' #-}
{-# INLINE mapMaybeStreamM #-}
filter :: Monad m => (a -> Bool) -> Steps m a -> Steps m a
filter f (Steps str k) = Steps (S.filter f str) (toLengthMax k)
{-# INLINE filter #-}
filterA :: (Monad m, Applicative f) => (e -> f Bool) -> Steps Id e -> f (Steps m e)
filterA f (Steps str k) = (`Steps` toLengthMax k) <$> liftListA (M.filterM f) str
{-# INLINE filterA #-}
filterM :: Monad m => (e -> m Bool) -> Steps m e -> Steps m e
filterM f (Steps str k) = Steps (S.filterM f str) (toLengthMax k)
{-# INLINE filterM #-}
take :: Monad m => Sz1 -> Steps m a -> Steps m a
take n (Steps str sz) =
Steps (S.take (coerce n) str) $!
case sz of
LengthExact k -> LengthExact (inline0 min n k)
LengthMax k -> LengthMax (inline0 min n k)
LengthUnknown -> LengthUnknown
{-# INLINE take #-}
drop :: Monad m => Sz1 -> Steps m a -> Steps m a
drop n (Steps str k) = Steps (S.drop (coerce n) str) (k `subtractLengthHint` LengthExact n)
{-# INLINE drop #-}
slice :: Monad m => Int -> Sz1 -> Steps m a -> Steps m a
slice i k (Steps str _) = Steps (S.slice i (coerce k) str) (LengthMax k)
{-# INLINE slice #-}
iterateN :: Monad m => Sz1 -> (a -> a) -> a -> Steps m a
iterateN n f a = Steps (S.iterateN (coerce n) f a) (LengthExact n)
{-# INLINE iterateN #-}
iterateNM :: Monad m => Sz1 -> (a -> m a) -> a -> Steps m a
iterateNM n f a = Steps (S.iterateNM (coerce n) f a) (LengthExact n)
{-# INLINE iterateNM #-}
replicate :: Monad m => Sz1 -> a -> Steps m a
replicate n a = Steps (S.replicate (coerce n) a) (LengthExact n)
{-# INLINE replicate #-}
replicateM :: Monad m => Sz1 -> m a -> Steps m a
replicateM n f = Steps (S.replicateM (coerce n) f) (LengthExact n)
{-# INLINE replicateM #-}
generateM :: Monad m => Sz1 -> (Int -> m a) -> Steps m a
generateM n f = Steps (S.generateM (coerce n) f) (LengthExact n)
{-# INLINE generateM #-}
unfoldr :: Monad m => (s -> Maybe (e, s)) -> s -> Steps m e
unfoldr f e0 = Steps (S.unfoldr f e0) LengthUnknown
{-# INLINE unfoldr #-}
unfoldrN :: Monad m => Sz1 -> (s -> Maybe (e, s)) -> s -> Steps m e
unfoldrN n f e0 = Steps (S.unfoldrN (coerce n) f e0) LengthUnknown
{-# INLINE unfoldrN #-}
unsafeUnfoldrN :: Monad m => Sz1 -> (s -> Maybe (e, s)) -> s -> Steps m e
unsafeUnfoldrN n f e0 = Steps (S.unfoldrN (coerce n) f e0) (LengthMax n)
{-# INLINE unsafeUnfoldrN #-}
unfoldrM :: Monad m => (s -> m (Maybe (e, s))) -> s -> Steps m e
unfoldrM f e0 = Steps (S.unfoldrM f e0) LengthUnknown
{-# INLINE unfoldrM #-}
unfoldrNM :: Monad m => Int -> (s -> m (Maybe (e, s))) -> s -> Steps m e
unfoldrNM n f e0 = Steps (S.unfoldrNM n f e0) LengthUnknown
{-# INLINE unfoldrNM #-}
unsafeUnfoldrNM :: Monad m => Sz1 -> (s -> m (Maybe (e, s))) -> s -> Steps m e
unsafeUnfoldrNM n f e0 = Steps (S.unfoldrNM (coerce n) f e0) (LengthMax n)
{-# INLINE unsafeUnfoldrNM #-}
unfoldrExactN :: Monad m => Sz1 -> (s -> (a, s)) -> s -> Steps m a
unfoldrExactN n f = unfoldrExactNM n (pure . f)
{-# INLINE unfoldrExactN #-}
unfoldrExactNM :: Monad m => Sz1 -> (s -> m (a, s)) -> s -> Steps m a
unfoldrExactNM n f t = Steps (S.Stream step (t, unSz n)) (LengthExact n)
where
step (s, i)
| i <= 0 = pure S.Done
| otherwise = fmap (\(x, s') -> S.Yield x (s', i - 1)) (f s)
{-# INLINE [0] step #-}
{-# INLINE unfoldrExactNM #-}
enumFromStepN :: (Num a, Monad m) => a -> a -> Sz1 -> Steps m a
enumFromStepN x step k = Steps (S.enumFromStepN x step (coerce k)) (LengthExact k)
{-# INLINE enumFromStepN #-}
toList :: Steps Id e -> [e]
toList (Steps str _) = unId (S.toList str)
{-# INLINE toList #-}
fromList :: Monad m => [e] -> Steps m e
fromList = (`Steps` LengthUnknown) . S.fromList
{-# INLINE fromList #-}
fromListN :: Monad m => Int -> [e] -> Steps m e
fromListN n = (`Steps` LengthUnknown) . S.fromListN n
{-# INLINE fromListN #-}
unsafeFromListN :: Monad m => Sz1 -> [e] -> Steps m e
unsafeFromListN n = (`Steps` LengthMax n) . S.fromListN (coerce n)
{-# INLINE unsafeFromListN #-}
liftListA :: (Monad m, Functor f) => ([a] -> f [b]) -> S.Stream Id a -> f (S.Stream m b)
liftListA f str = S.fromList <$> f (unId (S.toList str))
{-# INLINE liftListA #-}
transListM :: (Monad m, Monad n) => S.Stream m a -> m (S.Stream n a)
transListM str = do
xs <- S.toList str
pure $ S.fromList xs
{-# INLINE transListM #-}
transListNM :: (Monad m, Monad n) => S.Stream m a -> m (Sz1, S.Stream n a)
transListNM str = do
(n, xs) <- toListN str
pure (coerce n, S.fromList xs)
{-# INLINE transListNM #-}
toListN :: Monad m => S.Stream m a -> m (Int, [a])
toListN = S.foldr (\x (i, xs) -> (i + 1, x:xs)) (0, [])
{-# INLINE toListN #-}
sizeHintToBundleSize :: LengthHint -> B.Size
sizeHintToBundleSize =
\case
LengthExact k -> B.Exact (coerce k)
LengthMax k -> B.Max (coerce k)
LengthUnknown -> B.Unknown
{-# INLINE sizeHintToBundleSize #-}
addHint :: (Sz1 -> LengthHint) -> Int -> Int -> LengthHint
addHint hint m n
| k == coerce sz = hint sz
| otherwise = LengthUnknown -- overflow
where
k = m + n
sz = Sz k
{-# INLINE addHint #-}
addInt :: LengthHint -> Int -> LengthHint
addInt (LengthExact m) n = addHint LengthExact (coerce m) (coerce n)
addInt (LengthMax m) n = addHint LengthExact (coerce m) n
addInt _ _ = LengthUnknown
{-# INLINE addInt #-}
addLengthHint :: LengthHint -> LengthHint -> LengthHint
addLengthHint (LengthExact m) (LengthExact n) = addHint LengthExact (coerce m) (coerce n)
addLengthHint (LengthMax m) (LengthExact n) = addHint LengthMax (coerce m) (coerce n)
addLengthHint (LengthExact m) (LengthMax n) = addHint LengthMax (coerce m) (coerce n)
addLengthHint (LengthMax m) (LengthMax n) = addHint LengthMax (coerce m) (coerce n)
addLengthHint _ _ = LengthUnknown
{-# INLINE addLengthHint #-}
subtractLengthHint :: LengthHint -> LengthHint -> LengthHint
subtractLengthHint (LengthExact m) (LengthExact n) = LengthExact (m - n)
subtractLengthHint (LengthMax m) (LengthExact n) = LengthMax (m - n)
subtractLengthHint (LengthExact m) (LengthMax _) = LengthMax m
subtractLengthHint (LengthMax m) (LengthMax _) = LengthMax m
subtractLengthHint _ _ = LengthUnknown
{-# INLINE subtractLengthHint #-}
minLengthHint :: LengthHint -> LengthHint -> LengthHint
minLengthHint (LengthExact m) (LengthExact n) = LengthExact (inline0 min m n)
minLengthHint (LengthExact m) (LengthMax n) = LengthMax (inline0 min m n)
minLengthHint (LengthExact m) LengthUnknown = LengthMax m
minLengthHint (LengthMax m) (LengthExact n) = LengthMax (inline0 min m n)
minLengthHint (LengthMax m) (LengthMax n) = LengthMax (inline0 min m n)
minLengthHint (LengthMax m) LengthUnknown = LengthMax m
minLengthHint LengthUnknown (LengthExact n) = LengthMax n
minLengthHint LengthUnknown (LengthMax n) = LengthMax n
minLengthHint LengthUnknown LengthUnknown = LengthUnknown
{-# INLINE minLengthHint #-}
toLengthMax :: LengthHint -> LengthHint
toLengthMax (LengthExact n) = LengthMax n
toLengthMax (LengthMax n) = LengthMax n
toLengthMax LengthUnknown = LengthUnknown
{-# INLINE toLengthMax #-}