{-# LANGUAGE Rank2Types #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE LambdaCase #-}
module Haskus.Utils.Monad
( MonadInIO (..)
, module Control.Monad
, module Control.Monad.IO.Class
, module Control.Monad.Trans.Class
, whileM
, loop
, loopM
, whenM
, unlessM
, ifM
, notM
, anyM
, allM
, orM
, andM
)
where
import Control.Monad.IO.Class
import Control.Monad.Trans.Class
import Control.Monad
import Control.Monad.State
class MonadIO m => MonadInIO m where
liftWith :: (forall c. (a -> IO c) -> IO c) -> (a -> m b) -> m b
liftWith2 :: (forall c. (a -> b -> IO c) -> IO c) -> (a -> b -> m e) -> m e
instance MonadInIO IO where
{-# INLINABLE liftWith #-}
liftWith = id
{-# INLINABLE liftWith2 #-}
liftWith2 = id
instance MonadInIO m => MonadInIO (StateT s m) where
{-# INLINABLE liftWith #-}
liftWith wth f =
StateT $ \s -> do
liftWith wth (\a -> runStateT (f a) s)
{-# INLINABLE liftWith2 #-}
liftWith2 wth f =
StateT $ \s ->
liftWith2 wth (\a b -> runStateT (f a b) s)
whileM :: Monad m => m Bool -> m ()
whileM act = do
b <- act
when b $ whileM act
loop :: (a -> Either a b) -> a -> b
loop act x = case act x of
Left x' -> loop act x'
Right v -> v
loopM :: Monad m => (a -> m (Either a b)) -> a -> m b
loopM act x = act x >>= \case
Left x' -> loopM act x'
Right v -> return v
whenM :: Monad m => m Bool -> m () -> m ()
whenM b t = ifM b t (return ())
unlessM :: Monad m => m Bool -> m () -> m ()
unlessM b f = ifM b (return ()) f
ifM :: Monad m => m Bool -> m a -> m a -> m a
ifM mb t f = do
b <- mb
if b then t else f
notM :: Functor m => m Bool -> m Bool
notM = fmap not
anyM :: Monad m => (a -> m Bool) -> [a] -> m Bool
anyM _ [] = return False
anyM p (x:xs) = ifM (p x) (return True) (anyM p xs)
allM :: Monad m => (a -> m Bool) -> [a] -> m Bool
allM _ [] = return True
allM p (x:xs) = ifM (p x) (allM p xs) (return False)
orM :: Monad m => [m Bool] -> m Bool
orM = anyM id
andM :: Monad m => [m Bool] -> m Bool
andM = allM id