-- Hoogle documentation, generated by Haddock
-- See Hoogle, http://www.haskell.org/hoogle/


-- | Predicated traversal of generated trees
--   
--   Predicated traversal of generated trees.
@package hierarchy
@version 1.0.2

module Control.Cond

-- | <a>CondT</a> and its related combinators form a DSL to express
--   whether, given an item of type <tt>a</tt>: that item passes the
--   predicate, and/or if recursion should be performed from that item,
--   should it relate to the branch of a tree. This is used to build
--   predicates that can guide recursive traversals.
--   
--   For example, when recursing files in a directory tree, there are
--   several scenarios that <a>CondT</a> maybe consider:
--   
--   <ul>
--   <li>Whether the entry at a given path is of interest, independent from
--   its type (files or directories)</li>
--   <li>If the path is a directory, if the directory should be recursed
--   into.</li>
--   </ul>
--   
--   Yes or no answers are accepted for either criterion. This means that
--   the answer is "no" to both questions for a given directory, the
--   combinator <a>prune</a> should be used both to ignore the entry
--   itself, and to prevent recursion into its contents.
--   
--   Several different predicate types may be promoted to <a>CondT</a>:
--   
--   <ul>
--   <li><i><tt>Bool</tt></i> Using <a>guard</a></li>
--   <li><i><tt>m Bool</tt></i> Using <a>guardM</a></li>
--   <li><i><tt>a -&gt; Bool</tt></i> Using <a>guard_</a></li>
--   <li><i><tt>a -&gt; m Bool</tt></i> Using <a>guardM_</a></li>
--   <li><i><tt>a -&gt; m (Maybe r)</tt></i> Using <a>apply</a></li>
--   <li><i><tt>a -&gt; m (Maybe (r, a))</tt></i> Using
--   <a>consider</a></li>
--   </ul>
--   
--   Here is a trivial example:
--   
--   <pre>
--   flip runCondT 42 $ do
--     guard_ even
--     liftIO $ putStrLn "42 must be even to reach here"
--     guard_ odd &lt;|&gt; guard_ even
--     guard_ (== 42)
--   </pre>
--   
--   If <a>CondT</a> is executed using <a>runCondT</a>, it returns a
--   <tt>Maybe r</tt> if the predicate matched. It should usually be run
--   with <tt>applyCondT</tt>, which calls a continuation indicating wether
--   recursion should be performed.
data CondT a m r
type Cond a = CondT a Identity

-- | Apply a condition to an input value, returning a (possibly) updated
--   copy of that value if it matches, and the next <a>CondT</a> to use if
--   recursion into that value was indicated.
runCondT :: Monad m => a -> CondT a m r -> m ((Maybe r, Maybe (CondT a m r)), a)
runCond :: a -> Cond a r -> Maybe r
execCondT :: Monad m => a -> CondT a m r -> m (Maybe a, Maybe (CondT a m r))
evalCondT :: Monad m => a -> CondT a m r -> m (Maybe r)

-- | A specialized variant of <a>runCondT</a> that simply returns True or
--   False.
--   
--   <pre>
--   &gt;&gt;&gt; let good = guard_ (== "foo.hs") :: Cond String ()
--   
--   &gt;&gt;&gt; let bad  = guard_ (== "foo.hi") :: Cond String ()
--   
--   &gt;&gt;&gt; runIdentity $ test "foo.hs" $ not_ bad &gt;&gt; return "Success"
--   True
--   
--   &gt;&gt;&gt; runIdentity $ test "foo.hs" $ not_ good &gt;&gt; return "Shouldn't reach here"
--   False
--   </pre>
test :: Monad m => a -> CondT a m r -> m Bool

-- | <a>MonadQuery</a> is a custom version of <a>MonadReader</a>, created
--   so that users could still have their own <a>MonadReader</a> accessible
--   within conditionals.
class Monad m => MonadQuery a m | m -> a
query :: MonadQuery a m => m a
queries :: MonadQuery a m => (a -> b) -> m b
update :: MonadQuery a m => a -> m ()
updates :: MonadQuery a m => (a -> a) -> m ()
guardM :: MonadPlus m => m Bool -> m ()
guard_ :: (MonadPlus m, MonadQuery a m) => (a -> Bool) -> m ()
guardM_ :: (MonadPlus m, MonadQuery a m) => (a -> m Bool) -> m ()

-- | Apply a value-returning predicate. Note that whether or not this
--   return a <a>Just</a> value, recursion will be performed in the entry
--   itself, if applicable.
apply :: (MonadPlus m, MonadQuery a m) => (a -> m (Maybe r)) -> m r

-- | Consider an element, as <a>apply</a>, but returning a mutated form of
--   the element. This can be used to apply optimizations to speed future
--   conditions.
consider :: (MonadPlus m, MonadQuery a m) => (a -> m (Maybe (r, a))) -> m r
accept :: MonadPlus m => m ()

-- | <a>ignore</a> ignores the current entry, but allows recursion into its
--   descendents. This is the same as <a>empty</a>.
ignore :: MonadPlus m => m r

-- | <a>norecurse</a> prevents recursion into the current entry's
--   descendents, but does not ignore the entry itself.
norecurse :: Monad m => CondT a m ()

-- | <a>prune</a> is a synonym for both ignoring an entry and its
--   descendents.
prune :: Monad m => CondT a m r

-- | Return True or False depending on whether the given condition matches
--   or not. This differs from simply stating the condition in that it
--   itself always succeeds.
--   
--   <pre>
--   &gt;&gt;&gt; runCond "foo.hs" $ matches (guard =&lt;&lt; queries (== "foo.hs"))
--   Just True
--   
--   &gt;&gt;&gt; runCond "foo.hs" $ matches (guard =&lt;&lt; queries (== "foo.hi"))
--   Just False
--   </pre>
matches :: MonadPlus m => m r -> m Bool
ifM :: Monad m => m Bool -> m s -> m s -> m s
whenM :: Monad m => m Bool -> m s -> m ()
unlessM :: Monad m => m Bool -> m s -> m ()

-- | A variant of ifM which branches on whether the condition succeeds or
--   not. Note that <tt>if_ x</tt> is equivalent to <tt>ifM (matches
--   x)</tt>, and is provided solely for convenience.
--   
--   <pre>
--   &gt;&gt;&gt; let good = guard_ (== "foo.hs") :: Cond String ()
--   
--   &gt;&gt;&gt; let bad  = guard_ (== "foo.hi") :: Cond String ()
--   
--   &gt;&gt;&gt; runCond "foo.hs" $ if_ good (return "Success") (return "Failure")
--   Just "Success"
--   
--   &gt;&gt;&gt; runCond "foo.hs" $ if_ bad (return "Success") (return "Failure")
--   Just "Failure"
--   </pre>
if_ :: MonadPlus m => m r -> m s -> m s -> m s

-- | <a>when_</a> is just like <a>when</a>, except that it executes the
--   body if the condition passes, rather than based on a Bool value.
--   
--   <pre>
--   &gt;&gt;&gt; let good = guard_ (== "foo.hs") :: Cond String ()
--   
--   &gt;&gt;&gt; let bad  = guard_ (== "foo.hi") :: Cond String ()
--   
--   &gt;&gt;&gt; runCond "foo.hs" $ when_ good ignore
--   Nothing
--   
--   &gt;&gt;&gt; runCond "foo.hs" $ when_ bad ignore
--   Just ()
--   </pre>
when_ :: MonadPlus m => m r -> m s -> m ()

-- | <a>when_</a> is just like <a>when</a>, except that it executes the
--   body if the condition fails, rather than based on a Bool value.
--   
--   <pre>
--   &gt;&gt;&gt; let good = guard_ (== "foo.hs") :: Cond String ()
--   
--   &gt;&gt;&gt; let bad  = guard_ (== "foo.hi") :: Cond String ()
--   
--   &gt;&gt;&gt; runCond "foo.hs" $ unless_ bad ignore
--   Nothing
--   
--   &gt;&gt;&gt; runCond "foo.hs" $ unless_ good ignore
--   Just ()
--   </pre>
unless_ :: MonadPlus m => m r -> m s -> m ()

-- | Check whether at least one of the given conditions is true. This is a
--   synonym for <a>asum</a>.
--   
--   <pre>
--   &gt;&gt;&gt; let good = guard_ (== "foo.hs") :: Cond String ()
--   
--   &gt;&gt;&gt; let bad  = guard_ (== "foo.hi") :: Cond String ()
--   
--   &gt;&gt;&gt; runCond "foo.hs" $ or_ [bad, good]
--   Just ()
--   
--   &gt;&gt;&gt; runCond "foo.hs" $ or_ [bad]
--   Nothing
--   </pre>
or_ :: MonadPlus m => [m r] -> m r

-- | Check that all of the given conditions are true. This is a synonym for
--   <a>sequence_</a>.
--   
--   <pre>
--   &gt;&gt;&gt; let good = guard_ (== "foo.hs") :: Cond String ()
--   
--   &gt;&gt;&gt; let bad  = guard_ (== "foo.hi") :: Cond String ()
--   
--   &gt;&gt;&gt; runCond "foo.hs" $ and_ [bad, good]
--   Nothing
--   
--   &gt;&gt;&gt; runCond "foo.hs" $ and_ [good]
--   Just ()
--   </pre>
and_ :: MonadPlus m => [m r] -> m ()

-- | <a>not_</a> inverts the meaning of the given predicate.
--   
--   <pre>
--   &gt;&gt;&gt; let good = guard_ (== "foo.hs") :: Cond String ()
--   
--   &gt;&gt;&gt; let bad  = guard_ (== "foo.hi") :: Cond String ()
--   
--   &gt;&gt;&gt; runCond "foo.hs" $ not_ bad &gt;&gt; return "Success"
--   Just "Success"
--   
--   &gt;&gt;&gt; runCond "foo.hs" $ not_ good &gt;&gt; return "Shouldn't reach here"
--   Nothing
--   </pre>
not_ :: MonadPlus m => m r -> m ()

-- | <a>recurse</a> changes the recursion predicate for any child elements.
--   For example, the following file-finding predicate looks for all
--   <tt>*.hs</tt> files, but under any <tt>.git</tt> directory looks only
--   for a file named <tt>config</tt>:
--   
--   <pre>
--   if_ (name_ ".git" &gt;&gt; directory)
--       (ignore &gt;&gt; recurse (name_ "config"))
--       (glob "*.hs")
--   </pre>
--   
--   NOTE: If this code had used <tt>recurse (glob "*.hs"))</tt> instead in
--   the else case, it would have meant that <tt>.git</tt> is only looked
--   for at the top-level of the search (i.e., the top-most element).
recurse :: Monad m => CondT a m r -> CondT a m r
instance GHC.Base.Functor m => GHC.Base.Functor (Control.Cond.Recursor a m)
instance GHC.Base.Functor m => GHC.Base.Functor (Control.Cond.CondT a m)
instance GHC.Base.Monad m => Control.Cond.MonadQuery a (Control.Cond.CondT a m)
instance Control.Cond.MonadQuery r m => Control.Cond.MonadQuery r (Control.Monad.Trans.Reader.ReaderT r m)
instance (Control.Cond.MonadQuery r m, GHC.Base.Monoid w) => Control.Cond.MonadQuery r (Control.Monad.Trans.RWS.Lazy.RWST r w s m)
instance (Control.Cond.MonadQuery r m, GHC.Base.Monoid w) => Control.Cond.MonadQuery r (Control.Monad.Trans.RWS.Strict.RWST r w s m)
instance Control.Cond.MonadQuery r' m => Control.Cond.MonadQuery r' (Control.Monad.Trans.Cont.ContT r m)
instance (Control.Monad.Trans.Error.Error e, Control.Cond.MonadQuery r m) => Control.Cond.MonadQuery r (Control.Monad.Trans.Error.ErrorT e m)
instance Control.Cond.MonadQuery r m => Control.Cond.MonadQuery r (Control.Monad.Trans.Except.ExceptT e m)
instance Control.Cond.MonadQuery r m => Control.Cond.MonadQuery r (Control.Monad.Trans.Identity.IdentityT m)
instance Control.Cond.MonadQuery r m => Control.Cond.MonadQuery r (Control.Monad.Trans.List.ListT m)
instance Control.Cond.MonadQuery r m => Control.Cond.MonadQuery r (Control.Monad.Trans.Maybe.MaybeT m)
instance Control.Cond.MonadQuery r m => Control.Cond.MonadQuery r (Control.Monad.Trans.State.Lazy.StateT s m)
instance Control.Cond.MonadQuery r m => Control.Cond.MonadQuery r (Control.Monad.Trans.State.Strict.StateT s m)
instance (GHC.Base.Monoid w, Control.Cond.MonadQuery r m) => Control.Cond.MonadQuery r (Control.Monad.Trans.Writer.Lazy.WriterT w m)
instance (GHC.Base.Monoid w, Control.Cond.MonadQuery r m) => Control.Cond.MonadQuery r (Control.Monad.Trans.Writer.Strict.WriterT w m)
instance GHC.Base.Semigroup (Control.Cond.Recursor a m r)
instance GHC.Base.Monoid (Control.Cond.Recursor a m r)
instance Control.Monad.Morph.MFunctor (Control.Cond.Recursor a)
instance (GHC.Base.Monad m, GHC.Base.Semigroup r) => GHC.Base.Semigroup (Control.Cond.CondT a m r)
instance (GHC.Base.Monad m, GHC.Base.Monoid r) => GHC.Base.Monoid (Control.Cond.CondT a m r)
instance GHC.Base.Monad m => GHC.Base.Applicative (Control.Cond.CondT a m)
instance GHC.Base.Monad m => GHC.Base.Monad (Control.Cond.CondT a m)
instance Control.Monad.Reader.Class.MonadReader r m => Control.Monad.Reader.Class.MonadReader r (Control.Cond.CondT a m)
instance Control.Monad.Writer.Class.MonadWriter w m => Control.Monad.Writer.Class.MonadWriter w (Control.Cond.CondT a m)
instance Control.Monad.State.Class.MonadState s m => Control.Monad.State.Class.MonadState s (Control.Cond.CondT a m)
instance GHC.Base.Monad m => GHC.Base.Alternative (Control.Cond.CondT a m)
instance GHC.Base.Monad m => GHC.Base.MonadPlus (Control.Cond.CondT a m)
instance Control.Monad.Error.Class.MonadError e m => Control.Monad.Error.Class.MonadError e (Control.Cond.CondT a m)
instance Control.Monad.Catch.MonadThrow m => Control.Monad.Catch.MonadThrow (Control.Cond.CondT a m)
instance Control.Monad.Catch.MonadCatch m => Control.Monad.Catch.MonadCatch (Control.Cond.CondT a m)
instance Control.Monad.Catch.MonadMask m => Control.Monad.Catch.MonadMask (Control.Cond.CondT a m)
instance Control.Monad.Base.MonadBase b m => Control.Monad.Base.MonadBase b (Control.Cond.CondT a m)
instance Control.Monad.IO.Class.MonadIO m => Control.Monad.IO.Class.MonadIO (Control.Cond.CondT a m)
instance Control.Monad.Trans.Class.MonadTrans (Control.Cond.CondT a)
instance Control.Monad.Trans.Control.MonadBaseControl b m => Control.Monad.Trans.Control.MonadBaseControl b (Control.Cond.CondT r m)
instance Control.Monad.Morph.MFunctor (Control.Cond.CondT a)
instance Control.Monad.Cont.Class.MonadCont m => Control.Monad.Cont.Class.MonadCont (Control.Cond.CondT a m)
instance GHC.Base.Monad m => Control.Monad.Zip.MonadZip (Control.Cond.CondT a m)
instance Control.Monad.Fix.MonadFix m => Control.Monad.Fix.MonadFix (Control.Cond.CondT a m)

module Hierarchy

-- | A <a>TreeT</a> is a tree of values, where the (possible) branches are
--   represented by some MonadPlus <tt>m</tt>.
type TreeT m = CofreeT Maybe m

-- | Turn a list into a series of possibilities:
select :: MonadPlus m => [a] -> m a

-- | Descend one level into a <a>TreeT</a>, yielding a list of values and
--   their possible associated trees.
descend :: MonadPlus m => TreeT m a -> m (a, Maybe (TreeT m a))

-- | Perform a depth-first traversal of a <a>TreeT</a>, yielding each of
--   its contents. Note that breadth-first traversals cannot offer static
--   memory guarantees, so they are not provided by this module.
walk :: MonadPlus m => TreeT m a -> m a

-- | Given a <a>TreeT</a>, produce another <a>TreeT</a> which yields only
--   those elements (and sub-trees) matching the given monadic conditional.
--   This conditional (see <a>CondT</a>) can choose both elements and
--   points of recursion, making it capable of expressing any tree
--   traversal in the form of a predicate DSL. This differs from an
--   expression-based traversal, like XPath or Lens, in that effects in
--   <tt>m</tt> may be used to guide selection.
--   
--   For example, to print all Haskell files under the current directory:
--   
--   <pre>
--   let files = winnow (directoryFiles ".") $ do
--           path &lt;- query
--           liftIO $ putStrLn $ "Considering " ++ path
--           when (path <tt>`elem</tt>` [".<tt>/</tt>.git", ".<tt>/</tt>dist", ".<tt>/</tt>result"])
--               prune  -- ignore these, and don't recurse into them
--           guard_ (".hs" <tt>`isInfixOf</tt>`)  -- implicitly references <tt>path</tt>
--   forM_ (walk files) $ liftIO . print
--   </pre>
winnow :: MonadPlus m => TreeT m a -> CondT a m () -> TreeT m a
