mini-2.0.0.0: src/Mini/Transformers/Maybe.hs
-- | Extend a monad with the ability to terminate a computation without a value
module Mini.Transformers.Maybe (
-- * Type
MaybeT (
MaybeT
),
runMaybeT,
-- * Operations
maybeT,
nothing,
just,
) where
import Control.Applicative (
Alternative,
empty,
(<|>),
)
import Control.Monad (
ap,
liftM,
)
import Control.Monad.IO.Class (
MonadIO,
liftIO,
)
import Data.Bifunctor (
first,
)
import Mini.Random.Class (
Random,
random,
)
import Mini.Transformers.Class (
MonadTrans,
lift,
)
import Prelude (
Applicative,
Functor,
Maybe (
Just,
Nothing
),
Monad,
MonadFail,
const,
fail,
fmap,
maybe,
pure,
($),
(.),
(<*>),
(>>=),
)
-- Type
-- | A terminable transformer with inner monad /m/, return /a/
newtype MaybeT m a = MaybeT
{ runMaybeT :: m (Maybe a)
-- ^ Unwrap a transformer computation
}
instance (Monad m) => Functor (MaybeT m) where
fmap = liftM
instance (Monad m) => Applicative (MaybeT m) where
pure = just
(<*>) = ap
instance (Monad m) => Alternative (MaybeT m) where
empty = nothing
m <|> n = maybeT n just m
instance (Monad m) => Monad (MaybeT m) where
m >>= k = maybeT nothing k m
instance MonadTrans MaybeT where
lift = MaybeT . fmap Just
instance (Monad m) => MonadFail (MaybeT m) where
fail = const nothing
instance (MonadIO m) => MonadIO (MaybeT m) where
liftIO = lift . liftIO
instance (Monad m, Random a) => Random (MaybeT m a) where
random = first just . random
-- Operations
-- | Case analysis on the result of a computation
maybeT
:: (Monad m)
=> MaybeT m b
-- ^ Computation in case of @Nothing@
-> (a -> MaybeT m b)
-- ^ Function applied in case of @Just a@
-> MaybeT m a
-- ^ Object of the case analysis
-> MaybeT m b
maybeT n j m = MaybeT $ runMaybeT m >>= runMaybeT . maybe n j
-- | Terminate the computation without a value
nothing :: (Applicative m) => MaybeT m a
nothing = MaybeT $ pure Nothing
-- | Return a value
just :: (Applicative m) => a -> MaybeT m a
just = MaybeT . pure . Just