{-# LANGUAGE Arrows #-}
{-# LANGUAGE CPP #-}
{-# LANGUAGE Rank2Types #-}
module Control.Monad.Trans.MSF.Except
( module Control.Monad.Trans.MSF.Except
, module Control.Monad.Trans.Except
) where
import Control.Applicative
import qualified Control.Category as Category
import Control.Monad (liftM, ap)
import Control.Monad.Trans.Class
import Control.Monad.Trans.Except hiding (liftCallCC, liftListen, liftPass)
import Control.Monad.Trans.Maybe
import Data.MonadicStreamFunction
import Data.MonadicStreamFunction.InternalCore
#if __GLASGOW_HASKELL__ < 802
fromLeft :: a -> Either a b -> a
fromLeft _ (Left a) = a
fromLeft a (Right _) = a
fromRight :: b -> Either a b -> b
fromRight _ (Right b) = b
fromRight b (Left _) = b
#else
import Data.Either (fromLeft, fromRight)
#endif
throwOnCond :: Monad m => (a -> Bool) -> e -> MSF (ExceptT e m) a a
throwOnCond cond e = proc a -> if cond a
then throwS -< e
else returnA -< a
throwOnCondM :: Monad m => (a -> m Bool) -> e -> MSF (ExceptT e m) a a
throwOnCondM cond e = proc a -> do
b <- arrM (lift . cond) -< a
if b
then throwS -< e
else returnA -< a
throwOn :: Monad m => e -> MSF (ExceptT e m) Bool ()
throwOn e = proc b -> throwOn' -< (b, e)
throwOn' :: Monad m => MSF (ExceptT e m) (Bool, e) ()
throwOn' = proc (b, e) -> if b
then throwS -< e
else returnA -< ()
throwMaybe :: Monad m => MSF (ExceptT e m) (Maybe e) (Maybe a)
throwMaybe = mapMaybeS throwS
throwS :: Monad m => MSF (ExceptT e m) e a
throwS = arrM throwE
throw :: Monad m => e -> MSF (ExceptT e m) a b
throw = constM . throwE
pass :: Monad m => MSF (ExceptT e m) a a
pass = Category.id
maybeToExceptS :: (Functor m, Monad m)
=> MSF (MaybeT m) a b -> MSF (ExceptT () m) a b
maybeToExceptS = morphS (ExceptT . (maybe (Left ()) Right <$>) . runMaybeT)
catchS :: Monad m => MSF (ExceptT e m) a b -> (e -> MSF m a b) -> MSF m a b
catchS msf f = safely $ do
e <- try msf
safe $ f e
untilE :: Monad m => MSF m a b -> MSF m b (Maybe e)
-> MSF (ExceptT e m) a b
untilE msf msfe = proc a -> do
b <- liftTransS msf -< a
me <- liftTransS msfe -< b
inExceptT -< ExceptT $ return $ maybe (Right b) Left me
exceptS :: (Functor m, Monad m) => MSF (ExceptT e m) a b -> MSF m a (Either e b)
exceptS = transG return $ const $ fmap f . runExceptT
where
f (Left e) = (Left e , Nothing)
f (Right (b, c)) = (Right b, Just c )
inExceptT :: Monad m => MSF (ExceptT e m) (ExceptT e m a) a
inExceptT = arrM id
tagged :: Monad m => MSF (ExceptT e1 m) a b -> MSF (ExceptT e2 m) (a, e2) b
tagged msf = runMSFExcept $ do
_ <- try $ msf <<< arr fst
(_, e2) <- currentInput
return e2
newtype MSFExcept m a b e = MSFExcept { runMSFExcept :: MSF (ExceptT e m) a b }
try :: MSF (ExceptT e m) a b -> MSFExcept m a b e
try = MSFExcept
currentInput :: Monad m => MSFExcept m e b e
currentInput = try throwS
instance Monad m => Functor (MSFExcept m a b) where
fmap = liftM
instance Monad m => Applicative (MSFExcept m a b) where
pure = MSFExcept . throw
(<*>) = ap
instance Monad m => Monad (MSFExcept m a b) where
MSFExcept msf >>= f = MSFExcept $ handleExceptT msf $ runMSFExcept . f
handleExceptT
:: Monad m
=> MSF (ExceptT e1 m) a b
-> (e1 -> MSF (ExceptT e2 m) a b)
-> MSF (ExceptT e2 m) a b
handleExceptT msf f = flip handleGen msf $ \a mbcont -> do
ebcont <- lift $ runExceptT mbcont
case ebcont of
Left e -> unMSF (f e) a
Right (b, msf') -> return (b, handleExceptT msf' f)
data Empty
safely :: Monad m => MSFExcept m a b Empty -> MSF m a b
safely (MSFExcept msf) = morphS fromExcept msf
where
fromExcept ma = do
rightMa <- runExceptT ma
return $ fromRight (error "safely: Received `Left`") rightMa
safe :: Monad m => MSF m a b -> MSFExcept m a b e
safe = try . liftTransS
once :: Monad m => (a -> m e) -> MSFExcept m a b e
once f = try $ arrM (lift . f) >>> throwS
once_ :: Monad m => m e -> MSFExcept m a b e
once_ = once . const
step :: Monad m => (a -> m (b, e)) -> MSFExcept m a b e
step f = try $ proc a -> do
n <- count -< ()
(b, e) <- arrM (lift . f) -< a
_ <- throwOn' -< (n > (1 :: Int), e)
returnA -< b
performOnFirstSample :: Monad m => m (MSF m a b) -> MSF m a b
performOnFirstSample sfaction = safely $ do
msf <- once_ sfaction
safe msf
reactimateExcept :: Monad m => MSFExcept m () () e -> m e
reactimateExcept msfe = do
leftMe <- runExceptT $ reactimate $ runMSFExcept msfe
return $ fromLeft (error "reactimateExcept: Received `Right`") leftMe
reactimateB :: Monad m => MSF m () Bool -> m ()
reactimateB sf = reactimateExcept $ try $ liftTransS sf >>> throwOn ()
switch :: Monad m => MSF m a (b, Maybe c) -> (c -> MSF m a b) -> MSF m a b
switch sf f = catchS ef f
where
ef = proc a -> do
(b,me) <- liftTransS sf -< a
inExceptT -< ExceptT $ return $ maybe (Right b) Left me
transG :: (Monad m1, Monad m2)
=> (a2 -> m1 a1)
-> (forall c. a2 -> m1 (b1, c) -> m2 (b2, Maybe c))
-> MSF m1 a1 b1
-> MSF m2 a2 b2
transG transformInput transformOutput msf = go
where go = MSF $ \a2 -> do
(b2, msf') <- transformOutput a2 $ unMSF msf =<< transformInput a2
case msf' of
Just msf'' -> return (b2, transG transformInput transformOutput msf'')
Nothing -> return (b2, go)
handleGen :: (a -> m1 (b1, MSF m1 a b1) -> m2 (b2, MSF m2 a b2))
-> MSF m1 a b1
-> MSF m2 a b2
handleGen handler msf = MSF $ \a -> handler a (unMSF msf a)