Safe Haskell | None |
---|---|
Language | Haskell2010 |
- data CondT a m r
- type Cond a = CondT a Identity
- 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)
- test :: Monad m => a -> CondT a m r -> m Bool
- class Monad m => MonadQuery a m | m -> a where
- 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 :: (MonadPlus m, MonadQuery a m) => (a -> m (Maybe r)) -> m r
- consider :: (MonadPlus m, MonadQuery a m) => (a -> m (Maybe (r, a))) -> m r
- accept :: MonadPlus m => m ()
- ignore :: MonadPlus m => m r
- norecurse :: Monad m => CondT a m ()
- prune :: Monad m => CondT a m r
- matches :: MonadPlus m => m r -> m Bool
- if_ :: MonadPlus m => m r -> m s -> m s -> m s
- when_ :: MonadPlus m => m r -> m s -> m ()
- unless_ :: MonadPlus m => m r -> m s -> m ()
- or_ :: MonadPlus m => [m r] -> m r
- and_ :: MonadPlus m => [m r] -> m ()
- not_ :: MonadPlus m => m r -> m ()
- recurse :: Monad m => CondT a m r -> CondT a m r
Documentation
CondT
and its related combinators form a DSL to express whether, given
an item of type a
: 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 CondT
maybe consider:
- Whether the entry at a given path is of interest, independent from its type (files or directories)
- If the path is a directory, if the directory should be recursed into.
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
prune
should be used both to ignore the entry itself, and to prevent
recursion into its contents.
Several different predicate types may be promoted to CondT
:
Bool
- Using
guard
m Bool
- Using
guardM
a -> Bool
- Using
guard_
a -> m Bool
- Using
guardM_
a -> m (Maybe r)
- Using
apply
a -> m (Maybe (r, a))
- Using
consider
Here is a trivial example:
flip runCondT 42 $ do guard_ even liftIO $ putStrLn "42 must be even to reach here" guard_ odd <|> guard_ even guard_ (== 42)
If CondT
is executed using runCondT
, it returns a Maybe r
if the
predicate matched. It should usually be run with applyCondT
, which calls
a continuation indicating wether recursion should be performed.
MonadBase b m => MonadBase b (CondT a m) | |
MonadBaseControl b m => MonadBaseControl b (CondT r m) | |
MonadError e m => MonadError e (CondT a m) | |
MonadReader r m => MonadReader r (CondT a m) | |
MonadState s m => MonadState s (CondT a m) | |
MonadWriter w m => MonadWriter w (CondT a m) | |
Monad m => MonadQuery a (CondT a m) | |
MFunctor (CondT a) | |
MonadTrans (CondT a) | |
(Monad m, Functor m) => Alternative (CondT a m) | |
Monad m => Monad (CondT a m) | |
Functor m => Functor (CondT a m) | |
MonadFix m => MonadFix (CondT a m) | |
Monad m => MonadPlus (CondT a m) | |
(Monad m, Functor m) => Applicative (CondT a m) | |
Monad m => MonadZip (CondT a m) | |
MonadThrow m => MonadThrow (CondT a m) | |
MonadCatch m => MonadCatch (CondT a m) | |
MonadMask m => MonadMask (CondT a m) | |
MonadIO m => MonadIO (CondT a m) | |
MonadCont m => MonadCont (CondT a m) | |
(Monad m, Monoid r) => Monoid (CondT a m r) | |
(Monad m, Semigroup r) => Semigroup (CondT a m r) | |
type StM (CondT r m) a |
Executing CondT
runCondT :: Monad m => a -> CondT a m r -> m ((Maybe r, Maybe (CondT a m r)), a) Source
Apply a condition to an input value, returning a (possibly) updated copy
of that value if it matches, and the next CondT
to use if recursion into
that value was indicated.
test :: Monad m => a -> CondT a m r -> m Bool Source
A specialized variant of runCondT
that simply returns True or False.
>>>
let good = guard_ (== "foo.hs") :: Cond String ()
>>>
let bad = guard_ (== "foo.hi") :: Cond String ()
>>>
runIdentity $ test "foo.hs" $ not_ bad >> return "Success"
True>>>
runIdentity $ test "foo.hs" $ not_ good >> return "Shouldn't reach here"
False
Promotions
class Monad m => MonadQuery a m | m -> a where Source
MonadQuery
is a custom version of MonadReader
, created so that users
could still have their own MonadReader
accessible within conditionals.
MonadQuery r m => MonadQuery r (MaybeT m) | |
MonadQuery r m => MonadQuery r (ListT m) | |
MonadQuery r m => MonadQuery r (IdentityT m) | |
(Monoid w, MonadQuery r m) => MonadQuery r (WriterT w m) | |
(Monoid w, MonadQuery r m) => MonadQuery r (WriterT w m) | |
MonadQuery r m => MonadQuery r (StateT s m) | |
MonadQuery r m => MonadQuery r (StateT s m) | |
MonadQuery r m => MonadQuery r (ExceptT e m) | |
(Error e, MonadQuery r m) => MonadQuery r (ErrorT e m) | |
MonadQuery r' m => MonadQuery r' (ContT r m) | |
MonadQuery r m => MonadQuery r (ReaderT r m) | |
Monad m => MonadQuery a (CondT a m) | |
(MonadQuery r m, Monoid w) => MonadQuery r (RWST r w s m) | |
(MonadQuery r m, Monoid w) => MonadQuery r (RWST r w s m) |
guard_ :: (MonadPlus m, MonadQuery a m) => (a -> Bool) -> m () Source
guardM_ :: (MonadPlus m, MonadQuery a m) => (a -> m Bool) -> m () Source
apply :: (MonadPlus m, MonadQuery a m) => (a -> m (Maybe r)) -> m r Source
Apply a value-returning predicate. Note that whether or not this return a
Just
value, recursion will be performed in the entry itself, if
applicable.
consider :: (MonadPlus m, MonadQuery a m) => (a -> m (Maybe (r, a))) -> m r Source
Consider an element, as apply
, but returning a mutated form of the
element. This can be used to apply optimizations to speed future
conditions.
Basic conditionals
norecurse :: Monad m => CondT a m () Source
norecurse
prevents recursion into the current entry's descendents, but
does not ignore the entry itself.
prune :: Monad m => CondT a m r Source
prune
is a synonym for both ignoring an entry and its descendents. It
is the same as ignore >> norecurse
.
Boolean logic
matches :: MonadPlus m => m r -> m Bool Source
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.
>>>
runCond "foo.hs" $ matches (guard =<< queries (== "foo.hs"))
Just True>>>
runCond "foo.hs" $ matches (guard =<< queries (== "foo.hi"))
Just False
if_ :: MonadPlus m => m r -> m s -> m s -> m s Source
A variant of ifM which branches on whether the condition succeeds or not.
Note that if_ x
is equivalent to ifM (matches x)
, and is provided
solely for convenience.
>>>
let good = guard_ (== "foo.hs") :: Cond String ()
>>>
let bad = guard_ (== "foo.hi") :: Cond String ()
>>>
runCond "foo.hs" $ if_ good (return "Success") (return "Failure")
Just "Success">>>
runCond "foo.hs" $ if_ bad (return "Success") (return "Failure")
Just "Failure"
when_ :: MonadPlus m => m r -> m s -> m () Source
when_
is just like when
, except that it executes the body if the
condition passes, rather than based on a Bool value.
>>>
let good = guard_ (== "foo.hs") :: Cond String ()
>>>
let bad = guard_ (== "foo.hi") :: Cond String ()
>>>
runCond "foo.hs" $ when_ good ignore
Nothing>>>
runCond "foo.hs" $ when_ bad ignore
Just ()
unless_ :: MonadPlus m => m r -> m s -> m () Source
when_
is just like when
, except that it executes the body if the
condition fails, rather than based on a Bool value.
>>>
let good = guard_ (== "foo.hs") :: Cond String ()
>>>
let bad = guard_ (== "foo.hi") :: Cond String ()
>>>
runCond "foo.hs" $ unless_ bad ignore
Nothing>>>
runCond "foo.hs" $ unless_ good ignore
Just ()
or_ :: MonadPlus m => [m r] -> m r Source
Check whether at least one of the given conditions is true. This is a
synonym for asum
.
>>>
let good = guard_ (== "foo.hs") :: Cond String ()
>>>
let bad = guard_ (== "foo.hi") :: Cond String ()
>>>
runCond "foo.hs" $ or_ [bad, good]
Just ()>>>
runCond "foo.hs" $ or_ [bad]
Nothing
and_ :: MonadPlus m => [m r] -> m () Source
Check that all of the given conditions are true. This is a synonym for
sequence_
.
>>>
let good = guard_ (== "foo.hs") :: Cond String ()
>>>
let bad = guard_ (== "foo.hi") :: Cond String ()
>>>
runCond "foo.hs" $ and_ [bad, good]
Nothing>>>
runCond "foo.hs" $ and_ [good]
Just ()
not_ :: MonadPlus m => m r -> m () Source
not_
inverts the meaning of the given predicate.
>>>
let good = guard_ (== "foo.hs") :: Cond String ()
>>>
let bad = guard_ (== "foo.hi") :: Cond String ()
>>>
runCond "foo.hs" $ not_ bad >> return "Success"
Just "Success">>>
runCond "foo.hs" $ not_ good >> return "Shouldn't reach here"
Nothing
helper functions
recurse :: Monad m => CondT a m r -> CondT a m r Source
recurse
changes the recursion predicate for any child elements. For
example, the following file-finding predicate looks for all *.hs
files,
but under any .git
directory looks only for a file named config
:
if_ (name_ ".git" >> directory) (ignore >> recurse (name_ "config")) (glob "*.hs")
NOTE: If this code had used recurse (glob "*.hs"))
instead in the else
case, it would have meant that .git
is only looked for at the top-level
of the search (i.e., the top-most element).