module UnliftIO.Streams.Combinators
  ( filter
  , fold
  , foldM
  , map
  , mapM
  , unfoldM
  , zip
  ) where

import           Control.Monad.IO.Unlift (MonadUnliftIO, withRunInIO, liftIO)
import           Prelude hiding (filter, map, mapM, zip)
import           System.IO.Streams (InputStream)
import qualified System.IO.Streams.Combinators as SC

{-# INLINE filter #-}
filter :: (MonadUnliftIO m) => (a -> Bool) -> InputStream a -> m (InputStream a)
filter :: (a -> Bool) -> InputStream a -> m (InputStream a)
filter a -> Bool
f InputStream a
is = IO (InputStream a) -> m (InputStream a)
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (InputStream a) -> m (InputStream a))
-> IO (InputStream a) -> m (InputStream a)
forall a b. (a -> b) -> a -> b
$ (a -> Bool) -> InputStream a -> IO (InputStream a)
forall a. (a -> Bool) -> InputStream a -> IO (InputStream a)
SC.filter a -> Bool
f InputStream a
is

{-# INLINE fold #-}
fold :: (MonadUnliftIO m) => (s -> a -> s) -> s -> InputStream a -> m s
fold :: (s -> a -> s) -> s -> InputStream a -> m s
fold s -> a -> s
f s
s0 InputStream a
is = IO s -> m s
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO s -> m s) -> IO s -> m s
forall a b. (a -> b) -> a -> b
$ (s -> a -> s) -> s -> InputStream a -> IO s
forall s a. (s -> a -> s) -> s -> InputStream a -> IO s
SC.fold s -> a -> s
f s
s0 InputStream a
is

{-# INLINE foldM #-}
foldM :: MonadUnliftIO m => (s -> a -> m s) -> s -> InputStream a -> m s
foldM :: (s -> a -> m s) -> s -> InputStream a -> m s
foldM s -> a -> m s
f s
s0 InputStream a
is =
  ((forall a. m a -> IO a) -> IO s) -> m s
forall (m :: * -> *) b.
MonadUnliftIO m =>
((forall a. m a -> IO a) -> IO b) -> m b
withRunInIO (((forall a. m a -> IO a) -> IO s) -> m s)
-> ((forall a. m a -> IO a) -> IO s) -> m s
forall a b. (a -> b) -> a -> b
$ \forall a. m a -> IO a
io ->
    (s -> a -> IO s) -> s -> InputStream a -> IO s
forall s a. (s -> a -> IO s) -> s -> InputStream a -> IO s
SC.foldM (\s
s a
a -> m s -> IO s
forall a. m a -> IO a
io (m s -> IO s) -> m s -> IO s
forall a b. (a -> b) -> a -> b
$ s -> a -> m s
f s
s a
a) s
s0 InputStream a
is

{-# INLINE map #-}
map :: MonadUnliftIO m => (a -> b) -> InputStream a -> m (InputStream b)
map :: (a -> b) -> InputStream a -> m (InputStream b)
map a -> b
f InputStream a
is = IO (InputStream b) -> m (InputStream b)
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (InputStream b) -> m (InputStream b))
-> IO (InputStream b) -> m (InputStream b)
forall a b. (a -> b) -> a -> b
$ (a -> b) -> InputStream a -> IO (InputStream b)
forall a b. (a -> b) -> InputStream a -> IO (InputStream b)
SC.map a -> b
f InputStream a
is

{-# INLINE mapM #-}
mapM :: MonadUnliftIO m => (a -> m b) -> InputStream a -> m (InputStream b)
mapM :: (a -> m b) -> InputStream a -> m (InputStream b)
mapM a -> m b
f InputStream a
is =
  ((forall a. m a -> IO a) -> IO (InputStream b))
-> m (InputStream b)
forall (m :: * -> *) b.
MonadUnliftIO m =>
((forall a. m a -> IO a) -> IO b) -> m b
withRunInIO (((forall a. m a -> IO a) -> IO (InputStream b))
 -> m (InputStream b))
-> ((forall a. m a -> IO a) -> IO (InputStream b))
-> m (InputStream b)
forall a b. (a -> b) -> a -> b
$ \forall a. m a -> IO a
io ->
    (a -> IO b) -> InputStream a -> IO (InputStream b)
forall a b. (a -> IO b) -> InputStream a -> IO (InputStream b)
SC.mapM (m b -> IO b
forall a. m a -> IO a
io (m b -> IO b) -> (a -> m b) -> a -> IO b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> m b
f) InputStream a
is

{-# INLINE unfoldM #-}
unfoldM :: MonadUnliftIO m => (b -> m (Maybe (a, b))) -> b -> m (InputStream a)
unfoldM :: (b -> m (Maybe (a, b))) -> b -> m (InputStream a)
unfoldM b -> m (Maybe (a, b))
f b
s =
  ((forall a. m a -> IO a) -> IO (InputStream a))
-> m (InputStream a)
forall (m :: * -> *) b.
MonadUnliftIO m =>
((forall a. m a -> IO a) -> IO b) -> m b
withRunInIO (((forall a. m a -> IO a) -> IO (InputStream a))
 -> m (InputStream a))
-> ((forall a. m a -> IO a) -> IO (InputStream a))
-> m (InputStream a)
forall a b. (a -> b) -> a -> b
$ \forall a. m a -> IO a
io ->
    (b -> IO (Maybe (a, b))) -> b -> IO (InputStream a)
forall b a. (b -> IO (Maybe (a, b))) -> b -> IO (InputStream a)
SC.unfoldM (m (Maybe (a, b)) -> IO (Maybe (a, b))
forall a. m a -> IO a
io (m (Maybe (a, b)) -> IO (Maybe (a, b)))
-> (b -> m (Maybe (a, b))) -> b -> IO (Maybe (a, b))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. b -> m (Maybe (a, b))
f) b
s

{-# INLINE zip #-}
zip :: MonadUnliftIO m => InputStream a -> InputStream b -> m (InputStream (a, b))
zip :: InputStream a -> InputStream b -> m (InputStream (a, b))
zip InputStream a
as InputStream b
bs = IO (InputStream (a, b)) -> m (InputStream (a, b))
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (InputStream (a, b)) -> m (InputStream (a, b)))
-> IO (InputStream (a, b)) -> m (InputStream (a, b))
forall a b. (a -> b) -> a -> b
$ InputStream a -> InputStream b -> IO (InputStream (a, b))
forall a b.
InputStream a -> InputStream b -> IO (InputStream (a, b))
SC.zip InputStream a
as InputStream b
bs