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 :: forall (m :: * -> *) a.
MonadUnliftIO m =>
(a -> Bool) -> InputStream a -> m (InputStream a)
filter a -> Bool
f InputStream a
is = forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall a b. (a -> b) -> a -> b
$ 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 :: forall (m :: * -> *) s a.
MonadUnliftIO m =>
(s -> a -> s) -> s -> InputStream a -> m s
fold s -> a -> s
f s
s0 InputStream a
is = forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall a b. (a -> b) -> a -> b
$ 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 :: forall (m :: * -> *) s a.
MonadUnliftIO m =>
(s -> a -> m s) -> s -> InputStream a -> m s
foldM s -> a -> m s
f s
s0 InputStream a
is =
  forall (m :: * -> *) b.
MonadUnliftIO m =>
((forall a. m a -> IO a) -> IO b) -> m b
withRunInIO forall a b. (a -> b) -> a -> b
$ \forall a. m a -> IO a
io ->
    forall s a. (s -> a -> IO s) -> s -> InputStream a -> IO s
SC.foldM (\s
s a
a -> forall a. m a -> IO a
io 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 :: forall (m :: * -> *) a b.
MonadUnliftIO m =>
(a -> b) -> InputStream a -> m (InputStream b)
map a -> b
f InputStream a
is = forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall a b. (a -> b) -> a -> 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 :: forall (m :: * -> *) a b.
MonadUnliftIO m =>
(a -> m b) -> InputStream a -> m (InputStream b)
mapM a -> m b
f InputStream a
is =
  forall (m :: * -> *) b.
MonadUnliftIO m =>
((forall a. m a -> IO a) -> IO b) -> m b
withRunInIO forall a b. (a -> b) -> a -> b
$ \forall a. m a -> IO a
io ->
    forall a b. (a -> IO b) -> InputStream a -> IO (InputStream b)
SC.mapM (forall a. m a -> IO a
io 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 :: forall (m :: * -> *) b a.
MonadUnliftIO m =>
(b -> m (Maybe (a, b))) -> b -> m (InputStream a)
unfoldM b -> m (Maybe (a, b))
f b
s =
  forall (m :: * -> *) b.
MonadUnliftIO m =>
((forall a. m a -> IO a) -> IO b) -> m b
withRunInIO forall a b. (a -> b) -> a -> b
$ \forall a. m a -> IO a
io ->
    forall b a. (b -> IO (Maybe (a, b))) -> b -> IO (InputStream a)
SC.unfoldM (forall a. m a -> IO a
io 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 :: forall (m :: * -> *) a b.
MonadUnliftIO m =>
InputStream a -> InputStream b -> m (InputStream (a, b))
zip InputStream a
as InputStream b
bs = forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall a b. (a -> b) -> a -> b
$ forall a b.
InputStream a -> InputStream b -> IO (InputStream (a, b))
SC.zip InputStream a
as InputStream b
bs