-- | Extend a monad with the ability to terminate a computation without a value
module Mini.Transformers.MaybeT (
  -- * Type
  MaybeT (
    MaybeT
  ),

  -- * Runner
  runMaybeT,

  -- * Operations
  nothing,
  anticipate,
) where

import Control.Applicative (
  Alternative (
    empty,
    (<|>)
  ),
 )
import Control.Monad (
  ap,
  liftM,
  (>=>),
 )
import Mini.Transformers.Class (
  MonadTrans (
    lift
  ),
 )

{-
 - Type
 -}

-- | A terminable transformer with inner monad /m/, return /a/
newtype MaybeT m a = MaybeT
  { forall (m :: * -> *) a. MaybeT m a -> m (Maybe a)
runMaybeT :: m (Maybe a)
  -- ^ Unwrap a 'MaybeT' computation
  }

instance (Monad m) => Functor (MaybeT m) where
  fmap :: forall a b. (a -> b) -> MaybeT m a -> MaybeT m b
fmap = (a -> b) -> MaybeT m a -> MaybeT m b
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM

instance (Monad m) => Applicative (MaybeT m) where
  pure :: forall a. a -> MaybeT m a
pure = m (Maybe a) -> MaybeT m a
forall (m :: * -> *) a. m (Maybe a) -> MaybeT m a
MaybeT (m (Maybe a) -> MaybeT m a)
-> (a -> m (Maybe a)) -> a -> MaybeT m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Maybe a -> m (Maybe a)
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Maybe a -> m (Maybe a)) -> (a -> Maybe a) -> a -> m (Maybe a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Maybe a
forall a. a -> Maybe a
Just
  <*> :: forall a b. MaybeT m (a -> b) -> MaybeT m a -> MaybeT m b
(<*>) = MaybeT m (a -> b) -> MaybeT m a -> MaybeT m b
forall (m :: * -> *) a b. Monad m => m (a -> b) -> m a -> m b
ap

instance (Monad m) => Alternative (MaybeT m) where
  empty :: forall a. MaybeT m a
empty = m (Maybe a) -> MaybeT m a
forall (m :: * -> *) a. m (Maybe a) -> MaybeT m a
MaybeT (m (Maybe a) -> MaybeT m a) -> m (Maybe a) -> MaybeT m a
forall a b. (a -> b) -> a -> b
$ Maybe a -> m (Maybe a)
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Maybe a
forall a. Maybe a
Nothing
  MaybeT m a
m <|> :: forall a. MaybeT m a -> MaybeT m a -> MaybeT m a
<|> MaybeT m a
n =
    m (Maybe a) -> MaybeT m a
forall (m :: * -> *) a. m (Maybe a) -> MaybeT m a
MaybeT (m (Maybe a) -> MaybeT m a) -> m (Maybe a) -> MaybeT m a
forall a b. (a -> b) -> a -> b
$
      MaybeT m a -> m (Maybe a)
forall (m :: * -> *) a. MaybeT m a -> m (Maybe a)
runMaybeT MaybeT m a
m
        m (Maybe a) -> (Maybe a -> m (Maybe a)) -> m (Maybe a)
forall a b. m a -> (a -> m b) -> m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= m (Maybe a) -> (a -> m (Maybe a)) -> Maybe a -> m (Maybe a)
forall b a. b -> (a -> b) -> Maybe a -> b
maybe
          (MaybeT m a -> m (Maybe a)
forall (m :: * -> *) a. MaybeT m a -> m (Maybe a)
runMaybeT MaybeT m a
n)
          (Maybe a -> m (Maybe a)
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Maybe a -> m (Maybe a)) -> (a -> Maybe a) -> a -> m (Maybe a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Maybe a
forall a. a -> Maybe a
Just)

instance (Monad m) => Monad (MaybeT m) where
  MaybeT m a
m >>= :: forall a b. MaybeT m a -> (a -> MaybeT m b) -> MaybeT m b
>>= a -> MaybeT m b
k =
    m (Maybe b) -> MaybeT m b
forall (m :: * -> *) a. m (Maybe a) -> MaybeT m a
MaybeT (m (Maybe b) -> MaybeT m b) -> m (Maybe b) -> MaybeT m b
forall a b. (a -> b) -> a -> b
$
      MaybeT m a -> m (Maybe a)
forall (m :: * -> *) a. MaybeT m a -> m (Maybe a)
runMaybeT MaybeT m a
m
        m (Maybe a) -> (Maybe a -> m (Maybe b)) -> m (Maybe b)
forall a b. m a -> (a -> m b) -> m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= m (Maybe b) -> (a -> m (Maybe b)) -> Maybe a -> m (Maybe b)
forall b a. b -> (a -> b) -> Maybe a -> b
maybe
          (Maybe b -> m (Maybe b)
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Maybe b
forall a. Maybe a
Nothing)
          (MaybeT m b -> m (Maybe b)
forall (m :: * -> *) a. MaybeT m a -> m (Maybe a)
runMaybeT (MaybeT m b -> m (Maybe b))
-> (a -> MaybeT m b) -> a -> m (Maybe b)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> MaybeT m b
k)

instance MonadTrans MaybeT where
  lift :: forall (m :: * -> *) a. Monad m => m a -> MaybeT m a
lift = m (Maybe a) -> MaybeT m a
forall (m :: * -> *) a. m (Maybe a) -> MaybeT m a
MaybeT (m (Maybe a) -> MaybeT m a)
-> (m a -> m (Maybe a)) -> m a -> MaybeT m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> Maybe a) -> m a -> m (Maybe a)
forall a b. (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> Maybe a
forall a. a -> Maybe a
Just

{-
 - Operations
 -}

-- | Terminate the computation without a value
nothing :: (Monad m) => MaybeT m a
nothing :: forall (m :: * -> *) a. Monad m => MaybeT m a
nothing = MaybeT m a
forall a. MaybeT m a
forall (f :: * -> *) a. Alternative f => f a
empty

-- | Run a computation and get its result
anticipate :: (Monad m) => MaybeT m a -> MaybeT m (Maybe a)
anticipate :: forall (m :: * -> *) a. Monad m => MaybeT m a -> MaybeT m (Maybe a)
anticipate = m (Maybe (Maybe a)) -> MaybeT m (Maybe (Maybe a))
forall (m :: * -> *) a. Monad m => m a -> MaybeT m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m (Maybe (Maybe a)) -> MaybeT m (Maybe (Maybe a)))
-> (MaybeT m a -> m (Maybe (Maybe a)))
-> MaybeT m a
-> MaybeT m (Maybe (Maybe a))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MaybeT m (Maybe a) -> m (Maybe (Maybe a))
forall (m :: * -> *) a. MaybeT m a -> m (Maybe a)
runMaybeT (MaybeT m (Maybe a) -> m (Maybe (Maybe a)))
-> (MaybeT m a -> MaybeT m (Maybe a))
-> MaybeT m a
-> m (Maybe (Maybe a))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> Maybe a
forall a. a -> Maybe a
Just (a -> Maybe a) -> MaybeT m a -> MaybeT m (Maybe a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$>) (MaybeT m a -> MaybeT m (Maybe (Maybe a)))
-> (Maybe (Maybe a) -> MaybeT m (Maybe a))
-> MaybeT m a
-> MaybeT m (Maybe a)
forall (m :: * -> *) a b c.
Monad m =>
(a -> m b) -> (b -> m c) -> a -> m c
>=> MaybeT m (Maybe a)
-> (Maybe a -> MaybeT m (Maybe a))
-> Maybe (Maybe a)
-> MaybeT m (Maybe a)
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (Maybe a -> MaybeT m (Maybe a)
forall a. a -> MaybeT m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Maybe a
forall a. Maybe a
Nothing) Maybe a -> MaybeT m (Maybe a)
forall a. a -> MaybeT m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure