    -----------------------------------------------------------------------------
    -- |
    -- Module      :  Diagrams.Util
    -- Copyright   :  (c) 2011-2015 diagrams-lib team (see LICENSE)
    -- License     :  BSD-style (see LICENSE)
    -- Maintainer  :  diagrams-discuss@googlegroups.com
    --
    -- Some miscellaneous utilities provided by the diagrams-lib package.
    --
    -----------------------------------------------------------------------------

    module Diagrams.Util
      ( -- * Utilities for users

        with
      , applyAll
      , (#)
      , (##)

      , iterateN

      , tau

        -- * Finding files
      , findHsFile

        -- * Finding sandboxes
      , findSandbox
      , globalPackage

        -- * Internal utilities
      , foldB

      ) where

    import           Control.Applicative
    import           Control.Lens              hiding (( # ))
    import           Control.Monad
    import           Control.Monad.Catch
    import           Control.Monad.Trans
    import           Control.Monad.Trans.Maybe
    import           Data.Default.Class
    import           Data.List
    import           Data.List.Lens
    import           Data.Maybe
    import           Data.Monoid
    import           System.Directory
    import           System.Environment
    import           System.FilePath
    import           System.FilePath.Lens
    import           System.Process

    -- | Several functions exported by the diagrams library take a number
    --   of arguments giving the user control to \"tweak\" various aspects
    --   of their behavior.  Rather than give such functions a long list
    --   of arguments, and to make it possible for the user to selectively
    --   override only certain arguments and use default values for
    --   others, such sets of arguments are collected into a record with
    --   named fields (see 'PolygonOpts' in "Diagrams.TwoD.Shapes" for an
    --   example).  Such record types are made instances of the 'Default'
    --   class, which provides a single record structure ('def')
    --   collecting the \"default\" arguments to the function.  @with@ is
    --   a synonym for 'def', which provides nice-looking syntax for
    --   simulating optional, named arguments in Haskell.  For example,
    --
    --   @
    --   polygon with {sides = 7, edgeSkip = 2}
    --   @
    --
    --   calls the 'polygon' function with a single argument (note that
    --   record update binds more tightly than function application!),
    --   namely, 'with' (the record of default arguments) where the
    --   @sides@ and @edgeSkip@ fields have been updated.
    with :: Default d => d
    with :: d
    with = d
    forall a. Default a => a
    def

    -- | @applyAll@ takes a list of functions and applies them all to a
    --   value, in sequence from the last function in the list to the first.
    --   For example, @applyAll [f1, f2, f3] a == f1 . f2 . f3 $ a@.
    applyAll :: [a -> a] -> a -> a
    applyAll :: [a -> a] -> a -> a
    applyAll = Endo a -> a -> a
    forall a. Endo a -> a -> a
    appEndo (Endo a -> a -> a) -> ([a -> a] -> Endo a) -> [a -> a] -> a -> a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . [Endo a] -> Endo a
    forall a. Monoid a => [a] -> a
    mconcat ([Endo a] -> Endo a)
    -> ([a -> a] -> [Endo a]) -> [a -> a] -> Endo a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ((a -> a) -> Endo a) -> [a -> a] -> [Endo a]
    forall a b. (a -> b) -> [a] -> [b]
    map (a -> a) -> Endo a
    forall a. (a -> a) -> Endo a
    Endo

    infixl 8 #

    -- | Postfix function application, for conveniently applying
    --   attributes.  Unlike @($)@, @(#)@ has a high precedence (8), so @d
    --   \# foo \# bar@ can be combined with other things using operators
    --   like @(|||)@ or @(\<\>)@ without needing parentheses.
    (#) :: a -> (a -> b) -> b
    # :: a -> (a -> b) -> b
    (#) = ((a -> b) -> a -> b) -> a -> (a -> b) -> b
    forall a b c. (a -> b -> c) -> b -> a -> c
    flip (a -> b) -> a -> b
    forall a b. (a -> b) -> a -> b
    ($)

    -- | A replacement for lenses' 'Control.Lens.Review.#' operator.
    (##) :: AReview t b -> b -> t
    ## :: AReview t b -> b -> t
    (##) = AReview t b -> b -> t
    forall b (m :: * -> *) t. MonadReader b m => AReview t b -> m t
    review
    {-# INLINE (##) #-}
    infixr 8 ##

    -- | @iterateN n f x@ returns the list of the first @n@ iterates of
    --   @f@ starting at @x@, that is, the list @[x, f x, f (f x), ...]@
    --   of length @n@. (Note that the last element of the list will be
    --   @f@ applied to @x@ @(n-1)@ times.)
    iterateN :: Int -> (a -> a) -> a -> [a]
    iterateN :: Int -> (a -> a) -> a -> [a]
    iterateN n :: Int
    n f :: a -> a
    f = Int -> [a] -> [a]
    forall a. Int -> [a] -> [a]
    take Int
    n ([a] -> [a]) -> (a -> [a]) -> a -> [a]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (a -> a) -> a -> [a]
    forall a. (a -> a) -> a -> [a]
    iterate a -> a
    f

    -- | The circle constant, the ratio of a circle's circumference to its
    --   /radius/.  Note that @pi = tau/2@.
    --
    --   For more information and a well-reasoned argument why we should
    --   all be using tau instead of pi, see /The Tau Manifesto/,
    --   <http://tauday.com/>.
    --
    --   To hear what it sounds like (and to easily memorize the first 30
    --   digits or so), try <http://youtu.be/3174T-3-59Q>.
    tau :: Floating a => a
    tau :: a
    tau = 2a -> a -> a
    forall a. Num a => a -> a -> a
    *a
    forall a. Floating a => a
    pi

    -- | Given an associative binary operation and a default value to use
    --   in the case of an empty list, perform a /balanced/ fold over a
    --   list.  For example,
    --
    --   @
    --   foldB (+) z [a,b,c,d,e,f] == ((a+b) + (c+d)) + (e+f)
    --   @
    --
    foldB :: (a -> a -> a) -> a -> [a] -> a
    foldB :: (a -> a -> a) -> a -> [a] -> a
    foldB _ z :: a
    z [] = a
    z
    foldB f :: a -> a -> a
    f _ as :: [a]
    as = [a] -> a
    foldB' [a]
    as
      where foldB' :: [a] -> a
    foldB' [x :: a
    x] = a
    x
            foldB' xs :: [a]
    xs  = [a] -> a
    foldB' ([a] -> [a]
    go [a]
    xs)
            go :: [a] -> [a]
    go []         = []
            go [x :: a
    x]        = [a
    x]
            go (x1 :: a
    x1:x2 :: a
    x2:xs :: [a]
    xs) = a -> a -> a
    f a
    x1 a
    x2 a -> [a] -> [a]
    forall a. a -> [a] -> [a]
    : [a] -> [a]
    go [a]
    xs

    ------------------------------------------------------------------------
    -- Files
    ------------------------------------------------------------------------

    -- | Given some file (no extension or otherwise) try to find a haskell
    --   source file.
    findHsFile :: FilePath -> IO (Maybe FilePath)
    findHsFile :: FilePath -> IO (Maybe FilePath)
    findHsFile file :: FilePath
    file = MaybeT IO FilePath -> IO (Maybe FilePath)
    forall (m :: * -> *) a. MaybeT m a -> m (Maybe a)
    runMaybeT (MaybeT IO FilePath -> IO (Maybe FilePath))
    -> MaybeT IO FilePath -> IO (Maybe FilePath)
    forall a b. (a -> b) -> a -> b
    $ MaybeT IO FilePath
    hs MaybeT IO FilePath -> MaybeT IO FilePath -> MaybeT IO FilePath
    forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
    <|> MaybeT IO FilePath
    lhs
      where
        hs :: MaybeT IO FilePath
    hs      = FilePath -> MaybeT IO FilePath
    forall (t :: (* -> *) -> * -> *).
    (Monad (t IO), MonadTrans t, Alternative (t IO)) =>
    FilePath -> t IO FilePath
    check (FilePath -> FilePath -> FilePath
    addExtension FilePath
    file "hs")
        lhs :: MaybeT IO FilePath
    lhs     = FilePath -> MaybeT IO FilePath
    forall (t :: (* -> *) -> * -> *).
    (Monad (t IO), MonadTrans t, Alternative (t IO)) =>
    FilePath -> t IO FilePath
    check (FilePath -> FilePath -> FilePath
    addExtension FilePath
    file "lhs")
        check :: FilePath -> t IO FilePath
    check f :: FilePath
    f = do
          IO Bool -> t IO Bool
    forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
    (MonadTrans t, Monad m) =>
    m a -> t m a
    lift (FilePath -> IO Bool
    doesFileExist FilePath
    f) t IO Bool -> (Bool -> t IO ()) -> t IO ()
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= Bool -> t IO ()
    forall (f :: * -> *). Alternative f => Bool -> f ()
    guard
          FilePath -> t IO FilePath
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure FilePath
    f

    ------------------------------------------------------------------------
    -- Sandbox
    ------------------------------------------------------------------------

    -- | Parse cabal config file to find the location of the package
    --   database.
    parseConfig :: FilePath -> MaybeT IO FilePath
    parseConfig :: FilePath -> MaybeT IO FilePath
    parseConfig file :: FilePath
    file = do
      FilePath
    config <- IO FilePath -> MaybeT IO FilePath
    forall (m :: * -> *) a.
    (MonadCatch m, MonadIO m) =>
    IO a -> MaybeT m a
    maybeIO (IO FilePath -> MaybeT IO FilePath)
    -> IO FilePath -> MaybeT IO FilePath
    forall a b. (a -> b) -> a -> b
    $ FilePath -> IO FilePath
    readFile FilePath
    file
      Maybe FilePath -> MaybeT IO FilePath
    forall (m :: * -> *) a. Monad m => Maybe a -> MaybeT m a
    hoistMaybe (Maybe FilePath -> MaybeT IO FilePath)
    -> Maybe FilePath -> MaybeT IO FilePath
    forall a b. (a -> b) -> a -> b
    $ FilePath
    config FilePath
    -> Getting (First FilePath) FilePath FilePath -> Maybe FilePath
    forall s a. s -> Getting (First a) s a -> Maybe a
    ^? Getting (First FilePath) FilePath FilePath
    forall (f :: * -> *).
    Applicative f =>
    IndexedLensLike' Int f FilePath FilePath
    lined Getting (First FilePath) FilePath FilePath
    -> Getting (First FilePath) FilePath FilePath
    -> Getting (First FilePath) FilePath FilePath
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . FilePath -> Prism' FilePath FilePath
    forall a. Eq a => [a] -> Prism' [a] [a]
    prefixed "package-db: "

    -- | Seach the given directory and all parent directories until a cabal
    --   config file is found. First search for \"cabal.config\", then
    --   \"cabal.sandbox.config\". Return the location of the package
    --   database in the config file.
    configSearch :: FilePath -> MaybeT IO FilePath
    configSearch :: FilePath -> MaybeT IO FilePath
    configSearch p0 :: FilePath
    p0 = do
      FilePath
    p0' <- IO FilePath -> MaybeT IO FilePath
    forall (m :: * -> *) a.
    (MonadCatch m, MonadIO m) =>
    IO a -> MaybeT m a
    maybeIO (IO FilePath -> MaybeT IO FilePath)
    -> IO FilePath -> MaybeT IO FilePath
    forall a b. (a -> b) -> a -> b
    $ FilePath -> IO FilePath
    canonicalizePath FilePath
    p0

      let mkPaths :: FilePath -> [FilePath]
    mkPaths p :: FilePath
    p
            | (Char -> Bool) -> FilePath -> Bool
    forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
    all Char -> Bool
    isPathSeparator FilePath
    p Bool -> Bool -> Bool
    || FilePath
    p FilePath -> FilePath -> Bool
    forall a. Eq a => a -> a -> Bool
    == "."
                        = []
            | Bool
    otherwise = (FilePath
    p FilePath -> FilePath -> FilePath
    </> "cabal.sandbox.config")
                        FilePath -> [FilePath] -> [FilePath]
    forall a. a -> [a] -> [a]
    : FilePath -> [FilePath]
    mkPaths (FilePath
    p FilePath -> Getting FilePath FilePath FilePath -> FilePath
    forall s a. s -> Getting a s a -> a
    ^. Getting FilePath FilePath FilePath
    Lens' FilePath FilePath
    directory)

      (FilePath -> MaybeT IO FilePath)
    -> [FilePath] -> MaybeT IO FilePath
    forall (m :: * -> *) a b.
    Monad m =>
    (a -> MaybeT m b) -> [a] -> MaybeT m b
    foldMaybeT FilePath -> MaybeT IO FilePath
    parseConfig (FilePath -> [FilePath]
    mkPaths FilePath
    p0')

    -- | Check if the folder is a database, or if it contains a database.
    --   Returns the database location if it's found.
    isDB :: FilePath -> MaybeT IO FilePath
    isDB :: FilePath -> MaybeT IO FilePath
    isDB path :: FilePath
    path =
      if FilePath -> Bool
    isConf FilePath
    path
        then FilePath -> MaybeT IO FilePath
    forall (m :: * -> *) a. Monad m => a -> m a
    return FilePath
    path
        else IO [FilePath] -> MaybeT IO [FilePath]
    forall (m :: * -> *) a.
    (MonadCatch m, MonadIO m) =>
    IO a -> MaybeT m a
    maybeIO (FilePath -> IO [FilePath]
    getDirectoryContents FilePath
    path) MaybeT IO [FilePath]
    -> ([FilePath] -> MaybeT IO FilePath) -> MaybeT IO FilePath
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= Maybe FilePath -> MaybeT IO FilePath
    forall (m :: * -> *) a. Monad m => Maybe a -> MaybeT m a
    hoistMaybe (Maybe FilePath -> MaybeT IO FilePath)
    -> ([FilePath] -> Maybe FilePath)
    -> [FilePath]
    -> MaybeT IO FilePath
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (FilePath -> Bool) -> [FilePath] -> Maybe FilePath
    forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Maybe a
    find FilePath -> Bool
    isConf
        where
          isConf :: FilePath -> Bool
    isConf = FilePath -> FilePath -> Bool
    forall a. Eq a => [a] -> [a] -> Bool
    isSuffixOf ".conf.d"

    -- | Search for a sandbox in the following order:
    --
    --   * Test given FilePaths if they point directly to a database or
    --     contain a cabal config file (or any parent directory containing a
    --     config file).
    --
    --   * Same test for @DIAGRAMS_SANDBOX@ environment value
    --
    --   * Environment values of @GHC_PACKAGE_PATH@, @HSENV@ and
    --     @PACKAGE_DB_FOR_GHC@ that point to a database.
    --
    --   * Test for config file (cabal.sandbox.config) in the current
    --     directory and its parents.
    --
    findSandbox :: [FilePath] -> IO (Maybe FilePath)
    findSandbox :: [FilePath] -> IO (Maybe FilePath)
    findSandbox paths :: [FilePath]
    paths = MaybeT IO FilePath -> IO (Maybe FilePath)
    forall (m :: * -> *) a. MaybeT m a -> m (Maybe a)
    runMaybeT (MaybeT IO FilePath -> IO (Maybe FilePath))
    -> MaybeT IO FilePath -> IO (Maybe FilePath)
    forall a b. (a -> b) -> a -> b
    $ MaybeT IO FilePath
    pathsTest MaybeT IO FilePath -> MaybeT IO FilePath -> MaybeT IO FilePath
    forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
    <|> MaybeT IO FilePath
    diaSB MaybeT IO FilePath -> MaybeT IO FilePath -> MaybeT IO FilePath
    forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
    <|> MaybeT IO FilePath
    envDB MaybeT IO FilePath -> MaybeT IO FilePath -> MaybeT IO FilePath
    forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
    <|> MaybeT IO FilePath
    wdConfig
      where
        -- first path in environment
        lookEnv :: FilePath -> MaybeT IO FilePath
    lookEnv = IO (Maybe FilePath) -> MaybeT IO FilePath
    forall (m :: * -> *) a. m (Maybe a) -> MaybeT m a
    MaybeT (IO (Maybe FilePath) -> MaybeT IO FilePath)
    -> (FilePath -> IO (Maybe FilePath))
    -> FilePath
    -> MaybeT IO FilePath
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ((Maybe FilePath -> Maybe FilePath)
    -> IO (Maybe FilePath) -> IO (Maybe FilePath)
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap ((Maybe FilePath -> Maybe FilePath)
     -> IO (Maybe FilePath) -> IO (Maybe FilePath))
    -> ((FilePath -> FilePath) -> Maybe FilePath -> Maybe FilePath)
    -> (FilePath -> FilePath)
    -> IO (Maybe FilePath)
    -> IO (Maybe FilePath)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (FilePath -> FilePath) -> Maybe FilePath -> Maybe FilePath
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap) ([FilePath] -> FilePath
    forall a. [a] -> a
    head ([FilePath] -> FilePath)
    -> (FilePath -> [FilePath]) -> FilePath -> FilePath
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . FilePath -> [FilePath]
    splitSearchPath) (IO (Maybe FilePath) -> IO (Maybe FilePath))
    -> (FilePath -> IO (Maybe FilePath))
    -> FilePath
    -> IO (Maybe FilePath)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . FilePath -> IO (Maybe FilePath)
    lookupEnv
        envDB :: MaybeT IO FilePath
    envDB   = (FilePath -> MaybeT IO FilePath)
    -> [FilePath] -> MaybeT IO FilePath
    forall (m :: * -> *) a b.
    Monad m =>
    (a -> MaybeT m b) -> [a] -> MaybeT m b
    foldMaybeT FilePath -> MaybeT IO FilePath
    lookEnv ["GHC_PACKAGE_PATH", "HSENV", "PACKAGE_DB_FOR_GHC"]

        -- test if path points directly to db or contains a config file
        test :: FilePath -> MaybeT IO FilePath
    test x :: FilePath
    x    = FilePath -> MaybeT IO FilePath
    isDB FilePath
    x MaybeT IO FilePath -> MaybeT IO FilePath -> MaybeT IO FilePath
    forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
    <|> FilePath -> MaybeT IO FilePath
    configSearch FilePath
    x
        pathsTest :: MaybeT IO FilePath
    pathsTest = (FilePath -> MaybeT IO FilePath)
    -> [FilePath] -> MaybeT IO FilePath
    forall (m :: * -> *) a b.
    Monad m =>
    (a -> MaybeT m b) -> [a] -> MaybeT m b
    foldMaybeT FilePath -> MaybeT IO FilePath
    test [FilePath]
    paths
        diaSB :: MaybeT IO FilePath
    diaSB     = FilePath -> MaybeT IO FilePath
    lookEnv "DIAGRAMS_SANDBOX" MaybeT IO FilePath
    -> (FilePath -> MaybeT IO FilePath) -> MaybeT IO FilePath
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= FilePath -> MaybeT IO FilePath
    test
        wdConfig :: MaybeT IO FilePath
    wdConfig  = IO FilePath -> MaybeT IO FilePath
    forall (m :: * -> *) a.
    (MonadCatch m, MonadIO m) =>
    IO a -> MaybeT m a
    maybeIO IO FilePath
    getCurrentDirectory MaybeT IO FilePath
    -> (FilePath -> MaybeT IO FilePath) -> MaybeT IO FilePath
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= FilePath -> MaybeT IO FilePath
    configSearch

    -- -- | Use the given path for the sandbox in the @GHC_PACKAGE_PATH@
    -- --   environment (appending the ghc global package database from @ghc
    -- --   --info@. @GHC_PACKAGE_PATH@ if the variable ghc and other tools use
    -- --   to find the package database. (This is what @cabal exec@ sets)
    -- ghcPackagePath :: FilePath -> IO ()
    -- ghcPackagePath db = do
    --   gdb <- globalPackage
    --   let dbs = intercalate [searchPathSeparator] [db,gdb]
    --   setEnv "GHC_PACKAGE_PATH" dbs
    -- -- setEnv is only in base > 4.7, either need to use setenv package or
    -- -- -package-db flag

    -- | Find ghc's global package database. Throws an error if it isn't
    --   found.
    globalPackage :: IO FilePath
    globalPackage :: IO FilePath
    globalPackage = do
      [(FilePath, FilePath)]
    info <- FilePath -> [(FilePath, FilePath)]
    forall a. Read a => FilePath -> a
    read (FilePath -> [(FilePath, FilePath)])
    -> IO FilePath -> IO [(FilePath, FilePath)]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> FilePath -> [FilePath] -> FilePath -> IO FilePath
    readProcess "ghc" ["--info"] ""
      FilePath -> IO FilePath
    forall (m :: * -> *) a. Monad m => a -> m a
    return (FilePath -> IO FilePath) -> FilePath -> IO FilePath
    forall a b. (a -> b) -> a -> b
    $ FilePath -> Maybe FilePath -> FilePath
    forall a. a -> Maybe a -> a
    fromMaybe (FilePath -> FilePath
    forall a. HasCallStack => FilePath -> a
    error "Unable to parse ghc --info.")
                         (FilePath -> [(FilePath, FilePath)] -> Maybe FilePath
    forall a b. Eq a => a -> [(a, b)] -> Maybe b
    lookup "Global Package DB" [(FilePath, FilePath)]
    info)

    -- MaybeT utilities

    -- | Lift an 'IO' action. If any exceptions are raised, return Nothing.
    maybeIO :: (MonadCatch m, MonadIO m) => IO a -> MaybeT m a
    maybeIO :: IO a -> MaybeT m a
    maybeIO io :: IO a
    io = IO a -> MaybeT m a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO IO a
    io MaybeT m a -> (SomeException -> MaybeT m a) -> MaybeT m a
    forall (m :: * -> *) a.
    MonadCatch m =>
    m a -> (SomeException -> m a) -> m a
    `catchAll` MaybeT m a -> SomeException -> MaybeT m a
    forall a b. a -> b -> a
    const MaybeT m a
    forall (m :: * -> *) a. MonadPlus m => m a
    mzero

    -- | Lift a maybe value to a MaybeT of any monad.
    hoistMaybe :: Monad m => Maybe a -> MaybeT m a
    hoistMaybe :: Maybe a -> MaybeT m a
    hoistMaybe = m (Maybe a) -> MaybeT m a
    forall (m :: * -> *) a. m (Maybe a) -> MaybeT m a
    MaybeT (m (Maybe a) -> MaybeT m a)
    -> (Maybe a -> m (Maybe a)) -> Maybe a -> MaybeT m a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Maybe a -> m (Maybe a)
    forall (m :: * -> *) a. Monad m => a -> m a
    return

    -- | Fold a list of 'MaybeT's that short-circuits as soon as a Just value
    --   is found (instead going through the whole list).
    foldMaybeT :: Monad m => (a -> MaybeT m b) -> [a] -> MaybeT m b
    foldMaybeT :: (a -> MaybeT m b) -> [a] -> MaybeT m b
    foldMaybeT _ []     = MaybeT m b
    forall (m :: * -> *) a. MonadPlus m => m a
    mzero
    foldMaybeT f :: a -> MaybeT m b
    f (a :: a
    a:as :: [a]
    as) = 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
    $ do
      Maybe b
    x <- MaybeT m b -> m (Maybe b)
    forall (m :: * -> *) a. MaybeT m a -> m (Maybe a)
    runMaybeT (a -> MaybeT m b
    f a
    a)
      if Maybe b -> Bool
    forall a. Maybe a -> Bool
    isJust Maybe b
    x
        then Maybe b -> m (Maybe b)
    forall (m :: * -> *) a. Monad m => a -> m a
    return Maybe b
    x
        else MaybeT m b -> m (Maybe b)
    forall (m :: * -> *) a. MaybeT m a -> m (Maybe a)
    runMaybeT ((a -> MaybeT m b) -> [a] -> MaybeT m b
    forall (m :: * -> *) a b.
    Monad m =>
    (a -> MaybeT m b) -> [a] -> MaybeT m b
    foldMaybeT a -> MaybeT m b
    f [a]
    as)