{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE UndecidableInstances #-}
module Streamly.Prelude
(
nil
, consM
, (|:)
, cons
, (.:)
, unfoldr
, unfoldrM
, once
, replicateM
, repeatM
, iterate
, iterateM
, fromFoldable
, uncons
, foldr
, foldrM
, foldl'
, foldlM'
, foldx
, foldxM
, mapM_
, toList
, all
, any
, head
, tail
, last
, null
, length
, elem
, notElem
, maximum
, minimum
, sum
, product
, scanl'
, scanx
, filter
, take
, takeWhile
, drop
, dropWhile
, reverse
, mapM
, sequence
, zipWith
, zipWithM
, zipAsyncWith
, zipAsyncWithM
, fromHandle
, toHandle
, each
, scan
, foldl
, foldlM
)
where
import Control.Monad (void)
import Control.Monad.IO.Class (MonadIO(..))
import Data.Semigroup (Semigroup(..))
import Prelude hiding (filter, drop, dropWhile, take,
takeWhile, zipWith, foldr, foldl,
mapM, mapM_, sequence, all, any,
sum, product, elem, notElem,
maximum, minimum, head, last,
tail, length, null, reverse,
iterate)
import qualified Prelude
import qualified System.IO as IO
import qualified Streamly.Core as S
import Streamly.Core (Stream(Stream))
import Streamly.Streams
unfoldr :: IsStream t => (b -> Maybe (a, b)) -> b -> t m a
unfoldr step = fromStream . go
where
go s = Stream $ \_ stp _ yld ->
case step s of
Nothing -> stp
Just (a, b) -> yld a (go b)
unfoldrM :: (IsStream t, Monad m) => (b -> m (Maybe (a, b))) -> b -> t m a
unfoldrM step = fromStream . go
where
go s = Stream $ \_ stp _ yld -> do
mayb <- step s
case mayb of
Nothing -> stp
Just (a, b) -> yld a (go b)
{-# INLINE fromFoldable #-}
fromFoldable :: (IsStream t, Foldable f) => f a -> t m a
fromFoldable = Prelude.foldr cons nil
{-# DEPRECATED each "Please use fromFoldable instead." #-}
{-# INLINE each #-}
each :: (IsStream t, Foldable f) => f a -> t m a
each = fromFoldable
once :: (IsStream t, Monad m) => m a -> t m a
once = fromStream . S.once
replicateM :: (IsStream t, Monad m) => Int -> m a -> t m a
replicateM n m = fromStream $ go n
where
go cnt = Stream $ \_ stp _ yld ->
if cnt <= 0
then stp
else m >>= \a -> yld a (go (cnt - 1))
repeatM :: (IsStream t, Monad m) => m a -> t m a
repeatM = fromStream . go
where
go m = Stream $ \_ _ _ yld ->
m >>= \a -> yld a (go m)
iterate :: IsStream t => (a -> a) -> a -> t m a
iterate step = fromStream . go
where
go s = S.cons s (go (step s))
iterateM :: (IsStream t, Monad m) => (a -> m a) -> a -> t m a
iterateM step = fromStream . go
where
go s = Stream $ \_ _ _ yld -> do
a <- step s
yld s (go a)
fromHandle :: (IsStream t, MonadIO m) => IO.Handle -> t m String
fromHandle h = fromStream go
where
go = Stream $ \_ stp _ yld -> do
eof <- liftIO $ IO.hIsEOF h
if eof
then stp
else do
str <- liftIO $ IO.hGetLine h
yld str go
foldr :: Monad m => (a -> b -> b) -> b -> SerialT m a -> m b
foldr step acc m = go (toStream m)
where
go m1 =
let stop = return acc
single a = return (step a acc)
yield a r = go r >>= \b -> return (step a b)
in (S.runStream m1) Nothing stop single yield
{-# INLINE foldrM #-}
foldrM :: Monad m => (a -> b -> m b) -> b -> SerialT m a -> m b
foldrM step acc m = go (toStream m)
where
go m1 =
let stop = return acc
single a = step a acc
yield a r = go r >>= step a
in (S.runStream m1) Nothing stop single yield
{-# INLINE scanx #-}
scanx :: IsStream t => (x -> a -> x) -> x -> (x -> b) -> t m a -> t m b
scanx step begin done m = cons (done begin) $ fromStream $ go (toStream m) begin
where
go m1 !acc = Stream $ \_ stp sng yld ->
let single a = sng (done $ step acc a)
yield a r =
let s = step acc a
in yld (done s) (go r s)
in S.runStream m1 Nothing stp single yield
{-# DEPRECATED scan "Please use scanx instead." #-}
scan :: IsStream t => (x -> a -> x) -> x -> (x -> b) -> t m a -> t m b
scan = scanx
{-# INLINE scanl' #-}
scanl' :: IsStream t => (b -> a -> b) -> b -> t m a -> t m b
scanl' step begin m = scanx step begin id m
{-# INLINE foldx #-}
foldx :: Monad m => (x -> a -> x) -> x -> (x -> b) -> SerialT m a -> m b
foldx step begin done m = get $ go (toStream m) begin
where
{-# NOINLINE get #-}
get m1 =
let single = return . done
in (S.runStream m1) Nothing undefined single undefined
go m1 !acc = Stream $ \_ _ sng yld ->
let stop = sng acc
single a = sng $ step acc a
yield a r =
let stream = go r (step acc a)
in (S.runStream stream) Nothing undefined sng yld
in (S.runStream m1) Nothing stop single yield
{-# DEPRECATED foldl "Please use foldx instead." #-}
foldl :: Monad m => (x -> a -> x) -> x -> (x -> b) -> SerialT m a -> m b
foldl = foldx
{-# INLINE foldl' #-}
foldl' :: Monad m => (b -> a -> b) -> b -> SerialT m a -> m b
foldl' step begin m = foldx step begin id m
foldxM :: Monad m => (x -> a -> m x) -> m x -> (x -> m b) -> SerialT m a -> m b
foldxM step begin done m = go begin (toStream m)
where
go !acc m1 =
let stop = acc >>= done
single a = acc >>= \b -> step b a >>= done
yield a r = acc >>= \b -> go (step b a) r
in (S.runStream m1) Nothing stop single yield
{-# DEPRECATED foldlM "Please use foldxM instead." #-}
foldlM :: Monad m => (x -> a -> m x) -> m x -> (x -> m b) -> SerialT m a -> m b
foldlM = foldxM
foldlM' :: Monad m => (b -> a -> m b) -> b -> SerialT m a -> m b
foldlM' step begin m = foldxM step (return begin) return m
uncons :: (IsStream t, Monad m) => SerialT m a -> m (Maybe (a, t m a))
uncons m =
let stop = return Nothing
single a = return (Just (a, nil))
yield a r = return (Just (a, fromStream r))
in (S.runStream (toStream m)) Nothing stop single yield
toHandle :: MonadIO m => IO.Handle -> SerialT m String -> m ()
toHandle h m = go (toStream m)
where
go m1 =
let stop = return ()
single a = liftIO (IO.hPutStrLn h a)
yield a r = liftIO (IO.hPutStrLn h a) >> go r
in (S.runStream m1) Nothing stop single yield
{-# INLINABLE toList #-}
toList :: Monad m => SerialT m a -> m [a]
toList = foldrM (\a xs -> return (a : xs)) []
{-# INLINE take #-}
take :: IsStream t => Int -> t m a -> t m a
take n m = fromStream $ go n (toStream m)
where
go n1 m1 = Stream $ \ctx stp sng yld ->
let yield a r = yld a (go (n1 - 1) r)
in if n1 <= 0 then stp else (S.runStream m1) ctx stp sng yield
{-# INLINE filter #-}
filter :: IsStream t => (a -> Bool) -> t m a -> t m a
filter p m = fromStream $ go (toStream m)
where
go m1 = Stream $ \ctx stp sng yld ->
let single a | p a = sng a
| otherwise = stp
yield a r | p a = yld a (go r)
| otherwise = (S.runStream r) ctx stp single yield
in (S.runStream m1) ctx stp single yield
{-# INLINE takeWhile #-}
takeWhile :: IsStream t => (a -> Bool) -> t m a -> t m a
takeWhile p m = fromStream $ go (toStream m)
where
go m1 = Stream $ \ctx stp sng yld ->
let single a | p a = sng a
| otherwise = stp
yield a r | p a = yld a (go r)
| otherwise = stp
in (S.runStream m1) ctx stp single yield
drop :: IsStream t => Int -> t m a -> t m a
drop n m = fromStream $ go n (toStream m)
where
go n1 m1 = Stream $ \ctx stp sng yld ->
let single _ = stp
yield _ r = (S.runStream $ go (n1 - 1) r) ctx stp sng yld
in if n1 <= 0
then (S.runStream m1) ctx stp sng yld
else (S.runStream m1) ctx stp single yield
{-# INLINE dropWhile #-}
dropWhile :: IsStream t => (a -> Bool) -> t m a -> t m a
dropWhile p m = fromStream $ go (toStream m)
where
go m1 = Stream $ \ctx stp sng yld ->
let single a | p a = stp
| otherwise = sng a
yield a r | p a = (S.runStream r) ctx stp single yield
| otherwise = yld a r
in (S.runStream m1) ctx stp single yield
all :: Monad m => (a -> Bool) -> SerialT m a -> m Bool
all p m = go (toStream m)
where
go m1 =
let single a | p a = return True
| otherwise = return False
yield a r | p a = go r
| otherwise = return False
in (S.runStream m1) Nothing (return True) single yield
any :: Monad m => (a -> Bool) -> SerialT m a -> m Bool
any p m = go (toStream m)
where
go m1 =
let single a | p a = return True
| otherwise = return False
yield a r | p a = return True
| otherwise = go r
in (S.runStream m1) Nothing (return False) single yield
sum :: (Monad m, Num a) => SerialT m a -> m a
sum = foldl (+) 0 id
product :: (Monad m, Num a) => SerialT m a -> m a
product = foldl (*) 1 id
head :: Monad m => SerialT m a -> m (Maybe a)
head m =
let stop = return Nothing
single a = return (Just a)
yield a _ = return (Just a)
in (S.runStream (toStream m)) Nothing stop single yield
tail :: (IsStream t, Monad m) => SerialT m a -> m (Maybe (t m a))
tail m =
let stop = return Nothing
single _ = return $ Just nil
yield _ r = return $ Just $ fromStream r
in (S.runStream (toStream m)) Nothing stop single yield
{-# INLINE last #-}
last :: Monad m => SerialT m a -> m (Maybe a)
last = foldl (\_ y -> Just y) Nothing id
null :: Monad m => SerialT m a -> m Bool
null m =
let stop = return True
single _ = return False
yield _ _ = return False
in (S.runStream (toStream m)) Nothing stop single yield
elem :: (Monad m, Eq a) => a -> SerialT m a -> m Bool
elem e m = go (toStream m)
where
go m1 =
let stop = return False
single a = return (a == e)
yield a r = if a == e then return True else go r
in (S.runStream m1) Nothing stop single yield
notElem :: (Monad m, Eq a) => a -> SerialT m a -> m Bool
notElem e m = go (toStream m)
where
go m1 =
let stop = return True
single a = return (a /= e)
yield a r = if a == e then return False else go r
in (S.runStream m1) Nothing stop single yield
length :: Monad m => SerialT m a -> m Int
length = foldl (\n _ -> n + 1) 0 id
reverse :: (IsStream t) => t m a -> t m a
reverse m = fromStream $ go S.nil (toStream m)
where
go rev rest = Stream $ \svr stp sng yld ->
let run x = S.runStream x svr stp sng yld
stop = run rev
single a = run $ a `S.cons` rev
yield a r = run $ go (a `S.cons` rev) r
in S.runStream rest svr stop single yield
minimum :: (Monad m, Ord a) => SerialT m a -> m (Maybe a)
minimum m = go Nothing (toStream m)
where
go res m1 =
let stop = return res
single a = return $ min_ a res
yield a r = go (min_ a res) r
in (S.runStream m1) Nothing stop single yield
min_ a res = case res of
Nothing -> Just a
Just e -> Just $ min a e
maximum :: (Monad m, Ord a) => SerialT m a -> m (Maybe a)
maximum m = go Nothing (toStream m)
where
go res m1 =
let stop = return res
single a = return $ max_ a res
yield a r = go (max_ a res) r
in (S.runStream m1) Nothing stop single yield
max_ a res = case res of
Nothing -> Just a
Just e -> Just $ max a e
{-# INLINE mapM #-}
mapM :: (IsStream t, Monad m) => (a -> m b) -> t m a -> t m b
mapM f m = fromStream $ go (toStream m)
where
go m1 = Stream $ \_ stp sng yld ->
let single a = f a >>= sng
yield a r = f a >>= \b -> yld b (go r)
in (S.runStream m1) Nothing stp single yield
mapM_ :: Monad m => (a -> m b) -> SerialT m a -> m ()
mapM_ f m = go (toStream m)
where
go m1 =
let stop = return ()
single a = void (f a)
yield a r = f a >> go r
in (S.runStream m1) Nothing stop single yield
sequence :: (IsStream t, Monad m) => t m (m a) -> t m a
sequence m = fromStream $ go (toStream m)
where
go m1 = Stream $ \_ stp sng yld ->
let single ma = ma >>= sng
yield ma r = ma >>= \b -> yld b (go r)
in (S.runStream m1) Nothing stp single yield
zipWith :: IsStream t => (a -> b -> c) -> t m a -> t m b -> t m c
zipWith f m1 m2 = fromStream $ S.zipWith f (toStream m1) (toStream m2)
zipWithM :: IsStream t => (a -> b -> t m c) -> t m a -> t m b -> t m c
zipWithM f m1 m2 = fromStream $ go (toStream m1) (toStream m2)
where
go mx my = Stream $ \_ stp sng yld -> do
let merge a ra =
let run x = S.runStream x Nothing stp sng yld
single2 b = run $ toStream (f a b)
yield2 b rb = run $ toStream (f a b) <> go ra rb
in (S.runStream my) Nothing stp single2 yield2
let single1 a = merge a S.nil
yield1 a ra = merge a ra
(S.runStream mx) Nothing stp single1 yield1
zipAsyncWith :: (IsStream t, MonadAsync m)
=> (a -> b -> c) -> t m a -> t m b -> t m c
zipAsyncWith f m1 m2 =
fromStream $ S.zipAsyncWith f (toStream m1) (toStream m2)
zipAsyncWithM :: (IsStream t, MonadAsync m)
=> (a -> b -> t m c) -> t m a -> t m b -> t m c
zipAsyncWithM f m1 m2 = fromStream $ Stream $ \_ stp sng yld -> do
ma <- mkAsync m1
mb <- mkAsync m2
(S.runStream (toStream (zipWithM f ma mb))) Nothing stp sng yld