Safe Haskell | None |
---|---|
Language | Haskell2010 |
- data CondT a m r
- type Cond a = CondT a Identity
- runCondT :: Monad m => CondT a m r -> a -> m (Maybe r)
- runCond :: Cond a r -> a -> Maybe r
- applyCondT :: Monad m => a -> CondT a m r -> m (Maybe a, Maybe (CondT a m r))
- guardM :: MonadPlus m => m Bool -> m ()
- guard_ :: (MonadPlus m, MonadReader a m) => (a -> Bool) -> m ()
- guardM_ :: (MonadPlus m, MonadReader a m) => (a -> m Bool) -> m ()
- apply :: (MonadPlus m, MonadReader a m) => (a -> m (Maybe r)) -> m r
- consider :: (MonadPlus m, MonadState 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 :: (Monad m, Functor m) => CondT a m r -> CondT a m Bool
- if_ :: Monad m => CondT a m r -> CondT a m s -> CondT a m s -> CondT a m s
- when_ :: Monad m => CondT a m r -> CondT a m s -> CondT a m ()
- unless_ :: Monad m => CondT a m r -> CondT a m s -> CondT a m ()
- or_ :: Monad m => [CondT a m r] -> CondT a m r
- and_ :: Monad m => [CondT a m r] -> CondT a m ()
- not_ :: Monad m => CondT a m r -> CondT a m ()
- recurse :: Monad m => CondT a m r -> CondT a m r
- test :: Monad m => a -> CondT a m r -> m Bool
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) | |
Monad m => MonadReader a (CondT a m) | |
Monad m => MonadState 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) | |
Monad m => MonadPlus (CondT a m) | |
(Monad m, Functor m) => Applicative (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) | |
(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
applyCondT :: Monad m => a -> CondT a m r -> m (Maybe a, Maybe (CondT a m r)) 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.
Promotions
guard_ :: (MonadPlus m, MonadReader a m) => (a -> Bool) -> m () Source
guardM_ :: (MonadPlus m, MonadReader a m) => (a -> m Bool) -> m () Source
apply :: (MonadPlus m, MonadReader 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, MonadState 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 :: (Monad m, Functor m) => CondT a m r -> CondT a 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.
>>>
flip runCond "foo.hs" $ matches (guard =<< asks (== "foo.hs"))
Just True>>>
flip runCond "foo.hs" $ matches (guard =<< asks (== "foo.hi"))
Just False
if_ :: Monad m => CondT a m r -> CondT a m s -> CondT a m s -> CondT a 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 ()
>>>
flip runCond "foo.hs" $ if_ good (return "Success") (return "Failure")
Just "Success">>>
flip runCond "foo.hs" $ if_ bad (return "Success") (return "Failure")
Just "Failure"
when_ :: Monad m => CondT a m r -> CondT a m s -> CondT a 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 ()
>>>
flip runCond "foo.hs" $ when_ good ignore
Nothing>>>
flip runCond "foo.hs" $ when_ bad ignore
Just ()
unless_ :: Monad m => CondT a m r -> CondT a m s -> CondT a 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 ()
>>>
flip runCond "foo.hs" $ unless_ bad ignore
Nothing>>>
flip runCond "foo.hs" $ unless_ good ignore
Just ()
or_ :: Monad m => [CondT a m r] -> CondT a 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 ()
>>>
flip runCond "foo.hs" $ or_ [bad, good]
Just ()>>>
flip runCond "foo.hs" $ or_ [bad]
Nothing
and_ :: Monad m => [CondT a m r] -> CondT a 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 ()
>>>
flip runCond "foo.hs" $ and_ [bad, good]
Nothing>>>
flip runCond "foo.hs" $ and_ [good]
Just ()
not_ :: Monad m => CondT a m r -> CondT a m () Source
not_
inverts the meaning of the given predicate.
>>>
let good = guard_ (== "foo.hs") :: Cond String ()
>>>
let bad = guard_ (== "foo.hi") :: Cond String ()
>>>
flip runCond "foo.hs" $ not_ bad >> return "Success"
Just "Success">>>
flip 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).
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