immutaball-core-0.1.0.4.1: Control/Monad/Trans/MaybeM.hs
{-# OPTIONS_GHC -fno-warn-tabs #-} -- Support tab indentation better, for a better default of no warning if tabs are used: https://dmitryfrank.com/articles/indent_with_tabs_align_with_spaces .
-- Enable warnings:
{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}
-- State.hs.
{-# LANGUAGE Haskell2010 #-}
{-# LANGUAGE TemplateHaskell, InstanceSigs, ExplicitForAll, RankNTypes #-}
module Control.Monad.Trans.MaybeM
(
MaybeMT(..), maybeMT,
runMaybeMT,
runMaybeInMT,
MaybeM,
NaturalTransformation,
liftNaturalTransformation,
liftNT,
runMaybeM
) where
import Prelude ()
import Immutaball.Prelude
import Control.Applicative
import Control.Arrow
import Data.Functor.Identity
import Control.Lens
import Control.Monad
import Control.Monad.Fix
import Control.Monad.Trans.Class
import Control.Monad.Zip
newtype MaybeMT m a = MaybeMT { _maybeMT :: Either (m a) a }
deriving (Eq, Ord, Show, Read)
makeLenses ''MaybeMT
instance MonadTrans MaybeMT where
lift :: (Monad m) => m a -> MaybeMT m a
lift = MaybeMT . Left
runMaybeMT :: MaybeMT m a -> Either (m a) a
runMaybeMT = _maybeMT
runMaybeInMT :: (Applicative m) => MaybeMT m a -> m a
runMaybeInMT = (id ||| pure) . runMaybeMT
type MaybeM = MaybeMT Identity
instance (Functor m) => Functor (MaybeMT m) where
fmap :: (a -> b) -> (MaybeMT m a -> MaybeMT m b)
fmap f = MaybeMT . either (Left . fmap f) (Right . f) . runMaybeMT
instance (Applicative m) => Applicative (MaybeMT m) where
pure :: (Applicative m) => a -> MaybeMT m a
pure = MaybeMT . Right
(<*>) :: (Applicative m) => MaybeMT m (a -> b) -> MaybeMT m a -> MaybeMT m b
(MaybeMT (Right f)) <*> (MaybeMT (Right a)) = MaybeMT (Right (f a))
(MaybeMT (Left mf)) <*> (MaybeMT (Left ma)) = MaybeMT (Left (mf <*> ma))
(MaybeMT (Right f)) <*> (MaybeMT (Left ma)) = MaybeMT (Left (pure f <*> ma))
(MaybeMT (Left mf)) <*> (MaybeMT (Right a)) = MaybeMT (Left (mf <*> pure a))
instance (Monad m) => Monad (MaybeMT m) where
return :: (Monad m) => a -> MaybeMT m a
return = pure
(>>=) :: (Monad m) => MaybeMT m a -> (a -> MaybeMT m b) -> MaybeMT m b
(MaybeMT (Right a)) >>= f = f a
(MaybeMT (Left ma)) >>= f = MaybeMT . Left $ ma >>= \a -> either id return $ runMaybeMT (f a)
instance (Monad m, MonadFix m) => MonadFix (MaybeMT m) where
mfix :: (Monad m) => (a -> MaybeMT m a) -> MaybeMT m a
mfix f = MaybeMT . Left . mfix $ \a -> either id return $ runMaybeMT (f a)
instance (Alternative m) => Alternative (MaybeMT m) where
empty :: (Alternative m) => MaybeMT m a
empty = MaybeMT . Left $ empty
(<|>) :: (Alternative m) => MaybeMT m a -> MaybeMT m a -> MaybeMT m a
--x@( MaybeMT (Right _a)) <|> _ = x
_x@(MaybeMT (Right a)) <|> y = MaybeMT . Left $ pure a <|> (either id pure . runMaybeMT $ y)
_x@(MaybeMT (Left ma)) <|> y = MaybeMT . Left $ ma <|> (either id pure . runMaybeMT $ y)
instance (MonadPlus m) => MonadPlus (MaybeMT m) where
mzero :: (MonadPlus m) => MaybeMT m a
mzero = MaybeMT . Left $ mzero
mplus :: (MonadPlus m) => MaybeMT m a -> MaybeMT m a -> MaybeMT m a
--x@( MaybeMT (Right _a)) `mplus` _ = x
_x@(MaybeMT (Right a)) `mplus` y = MaybeMT . Left $ pure a `mplus` (either id pure . runMaybeMT $ y)
_x@(MaybeMT (Left ma)) `mplus` y = MaybeMT . Left $ ma `mplus` (either id pure . runMaybeMT $ y)
instance (Foldable m) => Foldable (MaybeMT m) where
foldr :: (Foldable m) => (a -> b -> b) -> b -> MaybeMT m a -> b
foldr reduce reduction0 (MaybeMT (Right a)) = reduce a reduction0
foldr reduce reduction0 (MaybeMT (Left ma)) = foldr reduce reduction0 ma
instance (Traversable m) => Traversable (MaybeMT m) where
traverse :: (Traversable m, Applicative f) => (a -> f b) -> MaybeMT m a -> f (MaybeMT m b)
traverse traversal_ (MaybeMT (Right a)) = pure (MaybeMT . Right) <*> traversal_ a
traverse traversal_ (MaybeMT (Left ma)) = pure (MaybeMT . Left) <*> traverse traversal_ ma
instance (MonadZip m) => MonadZip (MaybeMT m) where
mzip :: (MonadZip m) => MaybeMT m a -> MaybeMT m b -> MaybeMT m (a, b)
mzip (MaybeMT (Right a)) (MaybeMT (Right b)) = MaybeMT (Right (a, b))
mzip (MaybeMT (Left ma)) (MaybeMT (Left mb)) = MaybeMT (Left (mzip ma mb))
mzip (MaybeMT (Right a)) (MaybeMT (Left mb)) = MaybeMT (Left (mzip (pure a) mb))
mzip (MaybeMT (Left ma)) (MaybeMT (Right b)) = MaybeMT (Left (mzip ma (pure b)))
type NaturalTransformation m n = forall a. m a -> n a
-- | We _could_ require a natural transformation if we wanted, but since the
-- argument is to the _left_ of an arrow, not to the right, then rather than
-- outputting as specifically as we can, we want to input as generally as we
-- can.
--liftNaturalTransformation :: NaturalTransformation m n -> (MaybeMT m a -> MaybeMT n a)
liftNaturalTransformation :: (m a -> n a) -> (MaybeMT m a -> MaybeMT n a)
liftNaturalTransformation _nt (MaybeMT (Right a)) = MaybeMT (Right a)
liftNaturalTransformation nt (MaybeMT (Left ma)) = MaybeMT (Left (nt ma))
-- | Alias for 'liftNaturalTransformation'.
--liftNT :: NaturalTransformation m n -> (MaybeMT m a -> MaybeMT n a)
liftNT :: (m a -> n a) -> (MaybeMT m a -> MaybeMT n a)
liftNT = liftNaturalTransformation
-- | Simplify a MaybeMT if the possible monad is 'Identity'.
runMaybeM :: MaybeM a -> a
runMaybeM (MaybeMT (Right a)) = a
runMaybeM (MaybeMT (Left (Identity a))) = a