Safe Haskell | Safe-Inferred |
---|---|

Language | Haskell98 |

- newtype CondT a m b = CondT {}
- type Cond a = CondT a Identity
- runCondT :: Monad m => CondT a m b -> a -> m (Maybe b)
- runCond :: Cond a b -> a -> Maybe b
- applyCondT :: Monad m => a -> CondT a m b -> m ((Maybe b, Maybe (CondT a m b)), a)
- applyCond :: a -> Cond a b -> ((Maybe b, Maybe (Cond a b)), a)
- guardM :: Monad m => m Bool -> CondT a m ()
- guard_ :: Monad m => (a -> Bool) -> CondT a m ()
- guardM_ :: Monad m => (a -> m Bool) -> CondT a m ()
- apply :: Monad m => (a -> m (Maybe b)) -> CondT a m b
- consider :: Monad m => (a -> m (Maybe (b, a))) -> CondT a m b
- matches :: Monad m => CondT a m b -> CondT a m Bool
- if_ :: Monad m => CondT a m r -> CondT a m b -> CondT a m b -> CondT a m b
- when_ :: Monad m => CondT a m r -> CondT a m () -> CondT a m ()
- unless_ :: Monad m => CondT a m r -> CondT a m () -> CondT a m ()
- or_ :: Monad m => [CondT a m b] -> CondT a m b
- and_ :: Monad m => [CondT a m b] -> CondT a m ()
- not_ :: Monad m => CondT a m b -> CondT a m ()
- ignore :: Monad m => CondT a m b
- norecurse :: Monad m => CondT a m ()
- prune :: Monad m => CondT a m b
- recurse :: Monad m => CondT a m b -> CondT a m b
- test :: Monad m => a -> CondT a m b -> m Bool
- newtype CondEitherT a m b = CondEitherT (StateT a (EitherT (Maybe (Maybe (CondEitherT a m b))) m) (b, Maybe (Maybe (CondEitherT a m b))))
- fromCondT :: Monad m => CondT a m b -> CondEitherT a m b
- toCondT :: Monad m => CondEitherT a m b -> CondT a m b

# Documentation

`CondT`

is a kind of `StateT a (MaybeT m) b`

, which uses a special
`Result`

type instead of `Maybe`

to express whether recursion should be
performed from the item under consideration. This is used to build
predicates that can guide recursive traversals.

Several different 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 b)`

- Using
`apply`

`a -> m (Maybe (b, 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 return a `Maybe b`

if the
predicate matched. It can also be run with `applyCondT`

, which does case
analysis on the `Result`

, specifying how recursion should be performed from
the given `a`

value.

Monad m => MonadState a (CondT a m) | |

Monad m => MonadReader a (CondT a m) | |

MonadBase b m => MonadBase b (CondT a m) | |

MonadBaseControl b m => MonadBaseControl b (CondT r m) | |

MonadTrans (CondT a) | |

MFunctor (CondT a) | |

Monad m => Alternative (CondT a m) | |

Monad m => Monad (CondT a m) | |

Monad m => Functor (CondT a m) | |

Monad m => MonadPlus (CondT a m) | |

Monad m => Applicative (CondT a m) | |

MonadIO m => MonadIO (CondT a m) | |

MonadThrow m => MonadThrow (CondT a m) | |

MonadCatch m => MonadCatch (CondT a m) | |

MonadMask m => MonadMask (CondT a m) | |

Show (CondT a m b) | |

(Monad m, Monoid b) => Monoid (CondT a m b) | |

(Monad m, Semigroup b) => Semigroup (CondT a m b) | |

type StM (CondT r m) a |

# Executing CondT

applyCondT :: Monad m => a -> CondT a m b -> m ((Maybe b, Maybe (CondT a m b)), a) Source

Case analysis of applying a condition to an input value. The result is a pair whose first part is a pair of Maybes specifying if the input matched and if recursion is expected from this value, and whose second part is the (possibly) mutated input value.

applyCond :: a -> Cond a b -> ((Maybe b, Maybe (Cond a b)), a) Source

Case analysis of applying a pure condition to an input value. The result is a pair whose first part is a pair of Maybes specifying if the input matched and if recursion is expected from this value, and whose second part is the (possibly) mutated input value.

# Promotions

# Boolean logic

matches :: Monad m => CondT a m b -> 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.

`>>>`

Just True`flip runCond "foo.hs" $ matches (guard =<< asks (== "foo.hs"))`

`>>>`

Just False`flip runCond "foo.hs" $ matches (guard =<< asks (== "foo.hi"))`

if_ :: Monad m => CondT a m r -> CondT a m b -> CondT a m b -> CondT a m b 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 ()`

`>>>`

Just "Success"`flip runCond "foo.hs" $ if_ good (return "Success") (return "Failure")`

`>>>`

Just "Failure"`flip runCond "foo.hs" $ if_ bad (return "Success") (return "Failure")`

when_ :: Monad m => CondT a m r -> CondT a m () -> 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 ()`

`>>>`

Nothing`flip runCond "foo.hs" $ when_ good ignore`

`>>>`

Just ()`flip runCond "foo.hs" $ when_ bad ignore`

unless_ :: Monad m => CondT a m r -> CondT a m () -> 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 ()`

`>>>`

Nothing`flip runCond "foo.hs" $ unless_ bad ignore`

`>>>`

Just ()`flip runCond "foo.hs" $ unless_ good ignore`

or_ :: Monad m => [CondT a m b] -> CondT a m b 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 ()`

`>>>`

Just ()`flip runCond "foo.hs" $ or_ [bad, good]`

`>>>`

Nothing`flip runCond "foo.hs" $ or_ [bad]`

and_ :: Monad m => [CondT a m b] -> 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 ()`

`>>>`

Nothing`flip runCond "foo.hs" $ and_ [bad, good]`

`>>>`

Just ()`flip runCond "foo.hs" $ and_ [good]`

not_ :: Monad m => CondT a m b -> 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 ()`

`>>>`

Just "Success"`flip runCond "foo.hs" $ not_ bad >> return "Success"`

`>>>`

Nothing`flip runCond "foo.hs" $ not_ good >> return "Shouldn't reach here"`

# 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 b Source

`prune`

is a synonym for both ignoring an entry and its descendents. It
is the same as `ignore >> norecurse`

.

# Helper functions

recurse :: Monad m => CondT a m b -> CondT a m b 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 b -> 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 ()`

`>>>`

True`runIdentity $ test "foo.hs" $ not_ bad >> return "Success"`

`>>>`

False`runIdentity $ test "foo.hs" $ not_ good >> return "Shouldn't reach here"`

# Isomorphism with a stateful EitherT

newtype CondEitherT a m b Source

This type is for documentation only, and shows the isomorphism between
`CondT`

and `CondEitherT`

. The reason for using `Result`

is that it
makes meaning of the constructors more explicit.

CondEitherT (StateT a (EitherT (Maybe (Maybe (CondEitherT a m b))) m) (b, Maybe (Maybe (CondEitherT a m b)))) |

fromCondT :: Monad m => CondT a m b -> CondEitherT a m b Source

Witness one half of the isomorphism from `CondT`

to `CondEitherT`

.

toCondT :: Monad m => CondEitherT a m b -> CondT a m b Source

Witness the other half of the isomorphism from `CondEitherT`

to `CondT`

.