    {-# LANGUAGE ConstraintKinds #-}

    -- | Extra functions for "Control.Monad".
    --   These functions provide looping, list operations and booleans.
    --   If you need a wider selection of monad loops and list generalisations,
    --   see <https://hackage.haskell.org/package/monad-loops monad-loops>.
    module Control.Monad.Extra(
        module Control.Monad,
        whenJust, whenJustM,
        whenMaybe, whenMaybeM,
        unit,
        maybeM, fromMaybeM, eitherM,
        -- * Loops
        loop, loopM, whileM, whileJustM, untilJustM,
        -- * Lists
        partitionM, concatMapM, concatForM, mconcatMapM, mapMaybeM, findM, firstJustM,
        fold1M, fold1M_,
        -- * Booleans
        whenM, unlessM, ifM, notM, (||^), (&&^), orM, andM, anyM, allM
        ) where

    import Control.Monad
    import Control.Exception.Extra
    import Data.Maybe
    import Control.Applicative
    import Data.Monoid
    import Prelude

    -- General utilities

    -- | Perform some operation on 'Just', given the field inside the 'Just'.
    --
    -- > whenJust Nothing  print == pure ()
    -- > whenJust (Just 1) print == print 1
    whenJust :: Applicative m => Maybe a -> (a -> m ()) -> m ()
    whenJust :: Maybe a -> (a -> m ()) -> m ()
    whenJust mg :: Maybe a
    mg f :: a -> m ()
    f = m () -> (a -> m ()) -> Maybe a -> m ()
    forall b a. b -> (a -> b) -> Maybe a -> b
    maybe (() -> m ()
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure ()) a -> m ()
    f Maybe a
    mg

    -- | Like 'whenJust', but where the test can be monadic.
    whenJustM :: Monad m => m (Maybe a) -> (a -> m ()) -> m ()
    -- Can't reuse whenMaybe on GHC 7.8 or lower because Monad does not imply Applicative
    whenJustM :: m (Maybe a) -> (a -> m ()) -> m ()
    whenJustM mg :: m (Maybe a)
    mg f :: a -> m ()
    f = m () -> (a -> m ()) -> m (Maybe a) -> m ()
    forall (m :: * -> *) b a.
    Monad m =>
    m b -> (a -> m b) -> m (Maybe a) -> m b
    maybeM (() -> m ()
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure ()) a -> m ()
    f m (Maybe a)
    mg

    -- | Like 'when', but return either 'Nothing' if the predicate was 'False',
    --   of 'Just' with the result of the computation.
    --
    -- > whenMaybe True  (print 1) == fmap Just (print 1)
    -- > whenMaybe False (print 1) == pure Nothing
    whenMaybe :: Applicative m => Bool -> m a -> m (Maybe a)
    whenMaybe :: Bool -> m a -> m (Maybe a)
    whenMaybe b :: Bool
    b x :: m a
    x = if Bool
    b then a -> Maybe a
    forall a. a -> Maybe a
    Just (a -> Maybe a) -> m a -> m (Maybe a)
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> m a
    x else Maybe a -> m (Maybe a)
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure Maybe a
    forall a. Maybe a
    Nothing

    -- | Like 'whenMaybe', but where the test can be monadic.
    whenMaybeM :: Monad m => m Bool -> m a -> m (Maybe a)
    -- Can't reuse whenMaybe on GHC 7.8 or lower because Monad does not imply Applicative
    whenMaybeM :: m Bool -> m a -> m (Maybe a)
    whenMaybeM mb :: m Bool
    mb x :: m a
    x = do
        Bool
    b <- m Bool
    mb
        if Bool
    b then (a -> Maybe a) -> m a -> m (Maybe a)
    forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
    liftM a -> Maybe a
    forall a. a -> Maybe a
    Just m a
    x else Maybe a -> m (Maybe a)
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure Maybe a
    forall a. Maybe a
    Nothing

    -- | The identity function which requires the inner argument to be @()@. Useful for functions
    --   with overloaded return types.
    --
    -- > \(x :: Maybe ()) -> unit x == x
    unit :: m () -> m ()
    unit :: m () -> m ()
    unit = m () -> m ()
    forall a. a -> a
    id

    -- | Monadic generalisation of 'maybe'.
    maybeM :: Monad m => m b -> (a -> m b) -> m (Maybe a) -> m b
    maybeM :: m b -> (a -> m b) -> m (Maybe a) -> m b
    maybeM n :: m b
    n j :: a -> m b
    j x :: m (Maybe a)
    x = m b -> (a -> m b) -> Maybe a -> m b
    forall b a. b -> (a -> b) -> Maybe a -> b
    maybe m b
    n a -> m b
    j (Maybe a -> m b) -> m (Maybe a) -> m b
    forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
    =<< m (Maybe a)
    x

    -- | Monadic generalisation of 'fromMaybe'.
    fromMaybeM :: Monad m => m a -> m (Maybe a) -> m a
    fromMaybeM :: m a -> m (Maybe a) -> m a
    fromMaybeM n :: m a
    n x :: m (Maybe a)
    x = m a -> (a -> m a) -> m (Maybe a) -> m a
    forall (m :: * -> *) b a.
    Monad m =>
    m b -> (a -> m b) -> m (Maybe a) -> m b
    maybeM m a
    n a -> m a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure m (Maybe a)
    x

    -- | Monadic generalisation of 'either'.
    eitherM :: Monad m => (a -> m c) -> (b -> m c) -> m (Either a b) -> m c
    eitherM :: (a -> m c) -> (b -> m c) -> m (Either a b) -> m c
    eitherM l :: a -> m c
    l r :: b -> m c
    r x :: m (Either a b)
    x = (a -> m c) -> (b -> m c) -> Either a b -> m c
    forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
    either a -> m c
    l b -> m c
    r (Either a b -> m c) -> m (Either a b) -> m c
    forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
    =<< m (Either a b)
    x

    -- | A variant of 'foldM' that has no base case, and thus may only be applied to non-empty lists.
    --
    -- > fold1M (\x y -> Just x) [] == undefined
    -- > fold1M (\x y -> Just $ x + y) [1, 2, 3] == Just 6
    fold1M :: (Partial, Monad m) => (a -> a -> m a) -> [a] -> m a
    fold1M :: (a -> a -> m a) -> [a] -> m a
    fold1M f :: a -> a -> m a
    f (x :: a
    x:xs :: [a]
    xs) = (a -> a -> m a) -> a -> [a] -> m a
    forall (t :: * -> *) (m :: * -> *) b a.
    (Foldable t, Monad m) =>
    (b -> a -> m b) -> b -> t a -> m b
    foldM a -> a -> m a
    f a
    x [a]
    xs
    fold1M f :: a -> a -> m a
    f xs :: [a]
    xs = [Char] -> m a
    forall a. HasCallStack => [Char] -> a
    error "fold1M: empty list"

    -- | Like 'fold1M' but discards the result.
    fold1M_ :: (Partial, Monad m) => (a -> a -> m a) -> [a] -> m ()
    fold1M_ :: (a -> a -> m a) -> [a] -> m ()
    fold1M_ f :: a -> a -> m a
    f xs :: [a]
    xs = (a -> a -> m a) -> [a] -> m a
    forall (m :: * -> *) a.
    (HasCallStack, Monad m) =>
    (a -> a -> m a) -> [a] -> m a
    fold1M a -> a -> m a
    f [a]
    xs m a -> m () -> m ()
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> () -> m ()
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure ()

    -- Data.List for Monad

    -- | A version of 'partition' that works with a monadic predicate.
    --
    -- > partitionM (Just . even) [1,2,3] == Just ([2], [1,3])
    -- > partitionM (const Nothing) [1,2,3] == Nothing
    partitionM :: Monad m => (a -> m Bool) -> [a] -> m ([a], [a])
    partitionM :: (a -> m Bool) -> [a] -> m ([a], [a])
    partitionM f :: a -> m Bool
    f [] = ([a], [a]) -> m ([a], [a])
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure ([], [])
    partitionM f :: a -> m Bool
    f (x :: a
    x:xs :: [a]
    xs) = do
        Bool
    res <- a -> m Bool
    f a
    x
        (as :: [a]
    as,bs :: [a]
    bs) <- (a -> m Bool) -> [a] -> m ([a], [a])
    forall (m :: * -> *) a.
    Monad m =>
    (a -> m Bool) -> [a] -> m ([a], [a])
    partitionM a -> m Bool
    f [a]
    xs
        ([a], [a]) -> m ([a], [a])
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure ([a
    x | Bool
    res][a] -> [a] -> [a]
    forall a. [a] -> [a] -> [a]
    ++[a]
    as, [a
    x | Bool -> Bool
    not Bool
    res][a] -> [a] -> [a]
    forall a. [a] -> [a] -> [a]
    ++[a]
    bs)

    -- | A version of 'concatMap' that works with a monadic predicate.
    concatMapM :: Monad m => (a -> m [b]) -> [a] -> m [b]
    {-# INLINE concatMapM #-}
    concatMapM :: (a -> m [b]) -> [a] -> m [b]
    concatMapM op :: a -> m [b]
    op = (a -> m [b] -> m [b]) -> m [b] -> [a] -> m [b]
    forall (t :: * -> *) a b.
    Foldable t =>
    (a -> b -> b) -> b -> t a -> b
    foldr a -> m [b] -> m [b]
    f ([b] -> m [b]
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure [])
        where f :: a -> m [b] -> m [b]
    f x :: a
    x xs :: m [b]
    xs = do [b]
    x <- a -> m [b]
    op a
    x; if [b] -> Bool
    forall (t :: * -> *) a. Foldable t => t a -> Bool
    null [b]
    x then m [b]
    xs else do [b]
    xs <- m [b]
    xs; [b] -> m [b]
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure ([b] -> m [b]) -> [b] -> m [b]
    forall a b. (a -> b) -> a -> b
    $ [b]
    x[b] -> [b] -> [b]
    forall a. [a] -> [a] -> [a]
    ++[b]
    xs

    -- | Like 'concatMapM', but has its arguments flipped, so can be used
    --   instead of the common @fmap concat $ forM@ pattern.
    concatForM :: Monad m => [a] -> (a -> m [b]) -> m [b]
    concatForM :: [a] -> (a -> m [b]) -> m [b]
    concatForM = ((a -> m [b]) -> [a] -> m [b]) -> [a] -> (a -> m [b]) -> m [b]
    forall a b c. (a -> b -> c) -> b -> a -> c
    flip (a -> m [b]) -> [a] -> m [b]
    forall (m :: * -> *) a b. Monad m => (a -> m [b]) -> [a] -> m [b]
    concatMapM

    -- | A version of 'mconcatMap' that works with a monadic predicate.
    mconcatMapM :: (Monad m, Monoid b) => (a -> m b) -> [a] -> m b
    mconcatMapM :: (a -> m b) -> [a] -> m b
    mconcatMapM f :: a -> m b
    f = ([b] -> b) -> m [b] -> m b
    forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
    liftM [b] -> b
    forall a. Monoid a => [a] -> a
    mconcat (m [b] -> m b) -> ([a] -> m [b]) -> [a] -> m b
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (a -> m b) -> [a] -> m [b]
    forall (t :: * -> *) (m :: * -> *) a b.
    (Traversable t, Monad m) =>
    (a -> m b) -> t a -> m (t b)
    mapM a -> m b
    f

    -- | A version of 'mapMaybe' that works with a monadic predicate.
    mapMaybeM :: Monad m => (a -> m (Maybe b)) -> [a] -> m [b]
    {-# INLINE mapMaybeM #-}
    mapMaybeM :: (a -> m (Maybe b)) -> [a] -> m [b]
    mapMaybeM op :: a -> m (Maybe b)
    op = (a -> m [b] -> m [b]) -> m [b] -> [a] -> m [b]
    forall (t :: * -> *) a b.
    Foldable t =>
    (a -> b -> b) -> b -> t a -> b
    foldr a -> m [b] -> m [b]
    f ([b] -> m [b]
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure [])
        where f :: a -> m [b] -> m [b]
    f x :: a
    x xs :: m [b]
    xs = do Maybe b
    x <- a -> m (Maybe b)
    op a
    x; case Maybe b
    x of Nothing -> m [b]
    xs; Just x :: b
    x -> do [b]
    xs <- m [b]
    xs; [b] -> m [b]
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure ([b] -> m [b]) -> [b] -> m [b]
    forall a b. (a -> b) -> a -> b
    $ b
    xb -> [b] -> [b]
    forall a. a -> [a] -> [a]
    :[b]
    xs

    -- Looping

    -- | A looping operation, where the predicate returns 'Left' as a seed for the next loop
    --   or 'Right' to abort the loop.
    --
    -- > loop (\x -> if x < 10 then Left $ x * 2 else Right $ show x) 1 == "16"
    loop :: (a -> Either a b) -> a -> b
    loop :: (a -> Either a b) -> a -> b
    loop act :: a -> Either a b
    act x :: a
    x = case a -> Either a b
    act a
    x of
        Left x :: a
    x -> (a -> Either a b) -> a -> b
    forall a b. (a -> Either a b) -> a -> b
    loop a -> Either a b
    act a
    x
        Right v :: b
    v -> b
    v

    -- | A monadic version of 'loop', where the predicate returns 'Left' as a seed for the next loop
    --   or 'Right' to abort the loop.
    loopM :: Monad m => (a -> m (Either a b)) -> a -> m b
    loopM :: (a -> m (Either a b)) -> a -> m b
    loopM act :: a -> m (Either a b)
    act x :: a
    x = do
        Either a b
    res <- a -> m (Either a b)
    act a
    x
        case Either a b
    res of
            Left x :: a
    x -> (a -> m (Either a b)) -> a -> m b
    forall (m :: * -> *) a b.
    Monad m =>
    (a -> m (Either a b)) -> a -> m b
    loopM a -> m (Either a b)
    act a
    x
            Right v :: b
    v -> b -> m b
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure b
    v

    -- | Keep running an operation until it becomes 'False'. As an example:
    --
    -- @
    -- whileM $ do sleep 0.1; notM $ doesFileExist "foo.txt"
    -- readFile "foo.txt"
    -- @
    --
    --   If you need some state persisted between each test, use 'loopM'.
    whileM :: Monad m => m Bool -> m ()
    whileM :: m Bool -> m ()
    whileM act :: m Bool
    act = do
        Bool
    b <- m Bool
    act
        Bool -> m () -> m ()
    forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
    when Bool
    b (m () -> m ()) -> m () -> m ()
    forall a b. (a -> b) -> a -> b
    $ m Bool -> m ()
    forall (m :: * -> *). Monad m => m Bool -> m ()
    whileM m Bool
    act

    -- | Keep running an operation until it becomes a 'Nothing', accumulating the
    --   monoid results inside the 'Just's as the result of the overall loop.
    whileJustM :: (Monad m, Monoid a) => m (Maybe a) -> m a
    whileJustM :: m (Maybe a) -> m a
    whileJustM act :: m (Maybe a)
    act = a -> m a
    go a
    forall a. Monoid a => a
    mempty
      where
        go :: a -> m a
    go accum :: a
    accum = do
            Maybe a
    res <- m (Maybe a)
    act
            case Maybe a
    res of
                Nothing -> a -> m a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure a
    accum
                Just r :: a
    r -> a -> m a
    go (a -> m a) -> a -> m a
    forall a b. (a -> b) -> a -> b
    $! (a
    accum a -> a -> a
    forall a. Semigroup a => a -> a -> a
    <> a
    r) -- strict apply, otherwise space leaks

    -- | Keep running an operation until it becomes a 'Just', then return the value
    --   inside the 'Just' as the result of the overall loop.
    untilJustM :: Monad m => m (Maybe a) -> m a
    untilJustM :: m (Maybe a) -> m a
    untilJustM act :: m (Maybe a)
    act = do
        Maybe a
    res <- m (Maybe a)
    act
        case Maybe a
    res of
            Just r :: a
    r  -> a -> m a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure a
    r
            Nothing -> m (Maybe a) -> m a
    forall (m :: * -> *) a. Monad m => m (Maybe a) -> m a
    untilJustM m (Maybe a)
    act

    -- Booleans

    -- | Like 'when', but where the test can be monadic.
    whenM :: Monad m => m Bool -> m () -> m ()
    whenM :: m Bool -> m () -> m ()
    whenM b :: m Bool
    b t :: m ()
    t = m Bool -> m () -> m () -> m ()
    forall (m :: * -> *) a. Monad m => m Bool -> m a -> m a -> m a
    ifM m Bool
    b m ()
    t (() -> m ()
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure ())

    -- | Like 'unless', but where the test can be monadic.
    unlessM :: Monad m => m Bool -> m () -> m ()
    unlessM :: m Bool -> m () -> m ()
    unlessM b :: m Bool
    b f :: m ()
    f = m Bool -> m () -> m () -> m ()
    forall (m :: * -> *) a. Monad m => m Bool -> m a -> m a -> m a
    ifM m Bool
    b (() -> m ()
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure ()) m ()
    f

    -- | Like @if@, but where the test can be monadic.
    ifM :: Monad m => m Bool -> m a -> m a -> m a
    ifM :: m Bool -> m a -> m a -> m a
    ifM b :: m Bool
    b t :: m a
    t f :: m a
    f = do Bool
    b <- m Bool
    b; if Bool
    b then m a
    t else m a
    f

    -- | Like 'not', but where the test can be monadic.
    notM :: Functor m => m Bool -> m Bool
    notM :: m Bool -> m Bool
    notM = (Bool -> Bool) -> m Bool -> m Bool
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap Bool -> Bool
    not

    -- | The lazy '||' operator lifted to a monad. If the first
    --   argument evaluates to 'True' the second argument will not
    --   be evaluated.
    --
    -- > Just True  ||^ undefined  == Just True
    -- > Just False ||^ Just True  == Just True
    -- > Just False ||^ Just False == Just False
    (||^) :: Monad m => m Bool -> m Bool -> m Bool
    ||^ :: m Bool -> m Bool -> m Bool
    (||^) a :: m Bool
    a b :: m Bool
    b = m Bool -> m Bool -> m Bool -> m Bool
    forall (m :: * -> *) a. Monad m => m Bool -> m a -> m a -> m a
    ifM m Bool
    a (Bool -> m Bool
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure Bool
    True) m Bool
    b

    -- | The lazy '&&' operator lifted to a monad. If the first
    --   argument evaluates to 'False' the second argument will not
    --   be evaluated.
    --
    -- > Just False &&^ undefined  == Just False
    -- > Just True  &&^ Just True  == Just True
    -- > Just True  &&^ Just False == Just False
    (&&^) :: Monad m => m Bool -> m Bool -> m Bool
    &&^ :: m Bool -> m Bool -> m Bool
    (&&^) a :: m Bool
    a b :: m Bool
    b = m Bool -> m Bool -> m Bool -> m Bool
    forall (m :: * -> *) a. Monad m => m Bool -> m a -> m a -> m a
    ifM m Bool
    a m Bool
    b (Bool -> m Bool
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure Bool
    False)

    -- | A version of 'any' lifted to a monad. Retains the short-circuiting behaviour.
    --
    -- > anyM Just [False,True ,undefined] == Just True
    -- > anyM Just [False,False,undefined] == undefined
    -- > \(f :: Int -> Maybe Bool) xs -> anyM f xs == orM (map f xs)
    anyM :: Monad m => (a -> m Bool) -> [a] -> m Bool
    anyM :: (a -> m Bool) -> [a] -> m Bool
    anyM p :: a -> m Bool
    p = (a -> m Bool -> m Bool) -> m Bool -> [a] -> m Bool
    forall (t :: * -> *) a b.
    Foldable t =>
    (a -> b -> b) -> b -> t a -> b
    foldr (m Bool -> m Bool -> m Bool
    forall (m :: * -> *). Monad m => m Bool -> m Bool -> m Bool
    (||^) (m Bool -> m Bool -> m Bool)
    -> (a -> m Bool) -> a -> m Bool -> m Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . a -> m Bool
    p) (Bool -> m Bool
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure Bool
    False)

    -- | A version of 'all' lifted to a monad. Retains the short-circuiting behaviour.
    --
    -- > allM Just [True,False,undefined] == Just False
    -- > allM Just [True,True ,undefined] == undefined
    -- > \(f :: Int -> Maybe Bool) xs -> anyM f xs == orM (map f xs)
    allM :: Monad m => (a -> m Bool) -> [a] -> m Bool
    allM :: (a -> m Bool) -> [a] -> m Bool
    allM p :: a -> m Bool
    p = (a -> m Bool -> m Bool) -> m Bool -> [a] -> m Bool
    forall (t :: * -> *) a b.
    Foldable t =>
    (a -> b -> b) -> b -> t a -> b
    foldr (m Bool -> m Bool -> m Bool
    forall (m :: * -> *). Monad m => m Bool -> m Bool -> m Bool
    (&&^) (m Bool -> m Bool -> m Bool)
    -> (a -> m Bool) -> a -> m Bool -> m Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . a -> m Bool
    p) (Bool -> m Bool
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure Bool
    True)

    -- | A version of 'or' lifted to a monad. Retains the short-circuiting behaviour.
    --
    -- > orM [Just False,Just True ,undefined] == Just True
    -- > orM [Just False,Just False,undefined] == undefined
    -- > \xs -> Just (or xs) == orM (map Just xs)
    orM :: Monad m => [m Bool] -> m Bool
    orM :: [m Bool] -> m Bool
    orM = (m Bool -> m Bool) -> [m Bool] -> m Bool
    forall (m :: * -> *) a. Monad m => (a -> m Bool) -> [a] -> m Bool
    anyM m Bool -> m Bool
    forall a. a -> a
    id

    -- | A version of 'and' lifted to a monad. Retains the short-circuiting behaviour.
    --
    -- > andM [Just True,Just False,undefined] == Just False
    -- > andM [Just True,Just True ,undefined] == undefined
    -- > \xs -> Just (and xs) == andM (map Just xs)
    andM :: Monad m => [m Bool] -> m Bool
    andM :: [m Bool] -> m Bool
    andM = (m Bool -> m Bool) -> [m Bool] -> m Bool
    forall (m :: * -> *) a. Monad m => (a -> m Bool) -> [a] -> m Bool
    allM m Bool -> m Bool
    forall a. a -> a
    id

    -- Searching

    -- | Like 'find', but where the test can be monadic.
    --
    -- > findM (Just . isUpper) "teST"             == Just (Just 'S')
    -- > findM (Just . isUpper) "test"             == Just Nothing
    -- > findM (Just . const True) ["x",undefined] == Just (Just "x")
    findM :: Monad m => (a -> m Bool) -> [a] -> m (Maybe a)
    findM :: (a -> m Bool) -> [a] -> m (Maybe a)
    findM p :: a -> m Bool
    p = (a -> m (Maybe a) -> m (Maybe a))
    -> m (Maybe a) -> [a] -> m (Maybe a)
    forall (t :: * -> *) a b.
    Foldable t =>
    (a -> b -> b) -> b -> t a -> b
    foldr (\x :: a
    x -> m Bool -> m (Maybe a) -> m (Maybe a) -> m (Maybe a)
    forall (m :: * -> *) a. Monad m => m Bool -> m a -> m a -> m a
    ifM (a -> m Bool
    p a
    x) (Maybe a -> m (Maybe a)
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure (Maybe a -> m (Maybe a)) -> Maybe a -> m (Maybe a)
    forall a b. (a -> b) -> a -> b
    $ a -> Maybe a
    forall a. a -> Maybe a
    Just a
    x)) (Maybe a -> m (Maybe a)
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure Maybe a
    forall a. Maybe a
    Nothing)

    -- | Like 'findM', but also allows you to compute some additional information in the predicate.
    firstJustM :: Monad m => (a -> m (Maybe b)) -> [a] -> m (Maybe b)
    firstJustM :: (a -> m (Maybe b)) -> [a] -> m (Maybe b)
    firstJustM p :: a -> m (Maybe b)
    p [] = Maybe b -> m (Maybe b)
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure Maybe b
    forall a. Maybe a
    Nothing
    firstJustM p :: a -> m (Maybe b)
    p (x :: a
    x:xs :: [a]
    xs) = m (Maybe b) -> (b -> m (Maybe b)) -> m (Maybe b) -> m (Maybe b)
    forall (m :: * -> *) b a.
    Monad m =>
    m b -> (a -> m b) -> m (Maybe a) -> m b
    maybeM ((a -> m (Maybe b)) -> [a] -> m (Maybe b)
    forall (m :: * -> *) a b.
    Monad m =>
    (a -> m (Maybe b)) -> [a] -> m (Maybe b)
    firstJustM a -> m (Maybe b)
    p [a]
    xs) (Maybe b -> m (Maybe b)
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure (Maybe b -> m (Maybe b)) -> (b -> Maybe b) -> b -> m (Maybe b)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . b -> Maybe b
    forall a. a -> Maybe a
    Just) (a -> m (Maybe b)
    p a
    x)