@@ -27,6 +27,9 @@ module Asyncly.AsyncT
27 , zipWithM
27 , zipWithM
29 , ZipSerial (..)
29 , ZipSerial (..)
31 , interleave
34 , interleave
@@ -711,7 +714,7 @@ drop n m = AsyncT $ \ctx stp yld -> do
711-- Zipping Streams
714-- Zipping Streams
712------------------------------------------------------------------------------
715------------------------------------------------------------------------------
714−-- | Zip two AsyncT streams serially using a monadic function.
717+-- | Zip two AsyncT streams serially using a monadic zipping function.
715zipWithM :: MonadAsync m =>
718zipWithM :: MonadAsync m =>
716 (a -> b -> AsyncT m c) -> AsyncT m a -> AsyncT m b -> AsyncT m c
719 (a -> b -> AsyncT m c) -> AsyncT m a -> AsyncT m b -> AsyncT m c
717zipWithM f m1 m2 = AsyncT $ \_ stp yld -> do
720zipWithM f m1 m2 = AsyncT $ \_ stp yld -> do
@@ -724,7 +727,7 @@ zipWithM f m1 m2 = AsyncT $ \_ stp yld -> do
724 yield1 a (Just ra) = merge a ra
727 yield1 a (Just ra) = merge a ra
725 (runAsyncT m1) Nothing stp yield1
728 (runAsyncT m1) Nothing stp yield1
727−-- | Zip two AsyncT streams serially using a pure function.
730+-- | Zip two AsyncT streams serially using a pure zipping function.
728zipWith :: MonadAsync m
731zipWith :: MonadAsync m
729 => (a -> b -> c) -> AsyncT m a -> AsyncT m b -> AsyncT m c
732 => (a -> b -> c) -> AsyncT m a -> AsyncT m b -> AsyncT m c
730zipWith f m1 m2 = AsyncT $ \_ stp yld -> do
733zipWith f m1 m2 = AsyncT $ \_ stp yld -> do
@@ -746,6 +749,58 @@ instance MonadAsync m => Applicative (ZipSerial m) where
746 pure a = ZipSerial $ cycle1 (pure a)
749 pure a = ZipSerial $ cycle1 (pure a)
747 (ZipSerial xs) <*> (ZipSerial ys) = ZipSerial (zipWith id xs ys)
750 (ZipSerial xs) <*> (ZipSerial ys) = ZipSerial (zipWith id xs ys)
752+-- | The computation specified in the argument is pushed to a new thread and
753+-- the context is computation pulls output from the thread.
754+pushOneToCtx :: MonadAsync m => CtxType -> AsyncT m a -> m (Context m a)
755+pushOneToCtx ctype m = do
758+ CtxType _ FIFO -> do
759+ c <- getFifoCtx ctype
761+ CtxType _ LIFO -> do
762+ c <- getLifoCtx ctype
764+ -- Note: We must have all the work on the queue before sending the
765+ -- pushworker, otherwise the pushworker may exit before we even get a
767+ liftIO $ (enqueue ctx) m
771+async :: MonadAsync m => AsyncT m a -> m (AsyncT m a)
773+ ctx <- pushOneToCtx (CtxType Disjunction LIFO) m
774+ return $ pullFromCtx ctx
776+-- | Zip two AsyncT streams asyncly (i.e. both the streams are generated
777+-- concurrently) using a monadic zipping function.
778+zipAsyncWithM :: MonadAsync m
779+ => (a -> b -> AsyncT m c) -> AsyncT m a -> AsyncT m b -> AsyncT m c
780+zipAsyncWithM f m1 m2 = AsyncT $ \_ stp yld -> do
783+ (runAsyncT (zipWithM f ma mb)) Nothing stp yld
785+-- | Zip two AsyncT streams asyncly (i.e. both the streams are generated
786+-- concurrently) using a pure zipping function.
787+zipAsyncWith :: MonadAsync m
788+ => (a -> b -> c) -> AsyncT m a -> AsyncT m b -> AsyncT m c
789+zipAsyncWith f m1 m2 = AsyncT $ \_ stp yld -> do
792+ (runAsyncT (zipWith f ma mb)) Nothing stp yld
794+-- | Wrapper around AsyncT type with a parallel zipping Applicative instance
796+-- > f <$> ZipAsync xs1 <*> ... <*> ZipAsync xsN
797+newtype ZipAsync m a = ZipAsync {getZipAsync :: AsyncT m a}
800+instance MonadAsync m => Applicative (ZipAsync m) where
801+ pure a = ZipAsync $ cycle1 (pure a)
802+ (ZipAsync xs) <*> (ZipAsync ys) = ZipAsync (zipAsyncWith id xs ys)
749------------------------------------------------------------------------------
804------------------------------------------------------------------------------
750-- Utilities
805-- Utilities
751------------------------------------------------------------------------------
806------------------------------------------------------------------------------