SciFlow-0.7.0: src/Control/Arrow/Async.hs
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE UndecidableInstances #-}
-- | Asynchronous arrows over monads with MonadBaseControl IO, using
-- lifted-async.
module Control.Arrow.Async where
import Control.Arrow
import Control.Category
import Control.Concurrent.Async.Lifted
import Control.Monad.Trans.Control (MonadBaseControl)
import Prelude hiding (id, (.))
newtype AsyncA m a b = AsyncA { runAsyncA :: a -> m b }
instance Monad m => Category (AsyncA m) where
id = AsyncA return
(AsyncA f) . (AsyncA g) = AsyncA (\b -> g b >>= f)
-- | @since 2.01
instance MonadBaseControl IO m => Arrow (AsyncA m) where
arr f = AsyncA (return . f)
first (AsyncA f) = AsyncA (\ ~(b,d) -> f b >>= \c -> return (c,d))
second (AsyncA f) = AsyncA (\ ~(d,b) -> f b >>= \c -> return (d,c))
(AsyncA f) *** (AsyncA g) = AsyncA $ \ ~(a,b) ->
withAsync (f a) $ \c ->
withAsync (g b) $ \d ->
waitBoth c d
instance MonadBaseControl IO m => ArrowChoice (AsyncA m) where
left f = f +++ arr id
right f = arr id +++ f
f +++ g = (f >>> arr Left) ||| (g >>> arr Right)
AsyncA f ||| AsyncA g = AsyncA (either f g)