Safe Haskell | Safe |
---|---|
Language | Haskell98 |
A module of helper functions for use with Alloy. Most of the functions
have versions for pure functions (without suffix), applicative functors (A
suffix) and monads (M suffix) and sometimes the monadic version again with routes.
Generally, only the pure version is documented. The key functions you are likely
to need (or their suffixed versions) are applyBottomUp
and applyBottomUp2
,
and listifyDepth
.
- applyBottomUp :: (Alloy t (OneOp s) BaseOp, Alloy s BaseOp (OneOp s)) => (s -> s) -> t -> t
- applyBottomUpA :: (AlloyA t (OneOpA s) BaseOpA, AlloyA s BaseOpA (OneOpA s), Applicative f) => f (s -> s) -> t -> f t
- applyBottomUpM :: (AlloyA t (OneOpA s) BaseOpA, AlloyA s BaseOpA (OneOpA s), Monad m) => (s -> m s) -> t -> m t
- applyBottomUpMRoute :: (AlloyARoute t (OneOpARoute s) BaseOpARoute, AlloyARoute s BaseOpARoute (OneOpARoute s), Monad m) => ((s, Route s t) -> m s) -> t -> m t
- applyBottomUp2 :: (Alloy t (TwoOp sA sB) BaseOp, Alloy sA BaseOp (TwoOp sA sB), Alloy sB BaseOp (TwoOp sA sB)) => (sA -> sA) -> (sB -> sB) -> t -> t
- applyBottomUpA2 :: (AlloyA t (TwoOpA sA sB) BaseOpA, AlloyA sA BaseOpA (TwoOpA sA sB), AlloyA sB BaseOpA (TwoOpA sA sB), Applicative f) => f (sA -> sA) -> f (sB -> sB) -> t -> f t
- applyBottomUpM2 :: (AlloyA t (TwoOpA sA sB) BaseOpA, AlloyA sA BaseOpA (TwoOpA sA sB), AlloyA sB BaseOpA (TwoOpA sA sB), Monad m) => (sA -> m sA) -> (sB -> m sB) -> t -> m t
- applyBottomUpMRoute2 :: (AlloyARoute t (TwoOpARoute sA sB) BaseOpARoute, AlloyARoute sA BaseOpARoute (TwoOpARoute sA sB), AlloyARoute sB BaseOpARoute (TwoOpARoute sA sB), Monad m) => ((sA, Route sA t) -> m sA) -> ((sB, Route sB t) -> m sB) -> t -> m t
- listifyDepth :: (AlloyA t (OneOpA s) BaseOpA, AlloyA s BaseOpA (OneOpA s)) => (s -> Bool) -> t -> [s]
- listifyDepthRoute :: (AlloyARoute t (OneOpARoute s) BaseOpARoute, AlloyARoute s BaseOpARoute (OneOpARoute s)) => ((s, Route s t) -> Bool) -> t -> [(s, Route s t)]
- checkDepthM :: (Monad m, AlloyA t (OneOpA s) BaseOpA, AlloyA s BaseOpA (OneOpA s)) => (s -> m ()) -> t -> m ()
- checkDepthM2 :: (Monad m, AlloyA t (TwoOpA r s) BaseOpA, AlloyA r BaseOpA (TwoOpA r s), AlloyA s BaseOpA (TwoOpA r s)) => (r -> m ()) -> (s -> m ()) -> t -> m ()
- makeBottomUp :: Alloy t BaseOp opT => opT -> (t -> t) -> t -> t
- makeBottomUpA :: (AlloyA t BaseOpA opT, Applicative f) => opT f -> f (t -> t) -> t -> f t
- makeBottomUpM :: (AlloyA t BaseOpA opT, Monad m) => opT m -> (t -> m t) -> t -> m t
- makeBottomUpMRoute :: (Monad m, AlloyARoute t BaseOpARoute opT) => opT m outer -> ((t, Route t outer) -> m t) -> (t, Route t outer) -> m t
Functions to easily apply transformations throughout a data structure
applyBottomUp :: (Alloy t (OneOp s) BaseOp, Alloy s BaseOp (OneOp s)) => (s -> s) -> t -> t Source
Given a function that applies to a particular type (s
), automatically
applies that function to every instance of s
in a larger structure of
type t
, performing the transformations in a bottom-up fashion. It does a
depth first traversal in order of a constructor's children, descending
first and applying the function afterwards on the way back up.
This is equivalent to SYB's everywhere function, as it applies the function everywhere it can throughout the data structure. The function will not be applied to the results of your transformation, so the function cannot end up in infinite loop (unless the value you apply the function to is infinite!).
applyBottomUpA :: (AlloyA t (OneOpA s) BaseOpA, AlloyA s BaseOpA (OneOpA s), Applicative f) => f (s -> s) -> t -> f t Source
applyBottomUpM :: (AlloyA t (OneOpA s) BaseOpA, AlloyA s BaseOpA (OneOpA s), Monad m) => (s -> m s) -> t -> m t Source
applyBottomUpMRoute :: (AlloyARoute t (OneOpARoute s) BaseOpARoute, AlloyARoute s BaseOpARoute (OneOpARoute s), Monad m) => ((s, Route s t) -> m s) -> t -> m t Source
applyBottomUp2 :: (Alloy t (TwoOp sA sB) BaseOp, Alloy sA BaseOp (TwoOp sA sB), Alloy sB BaseOp (TwoOp sA sB)) => (sA -> sA) -> (sB -> sB) -> t -> t Source
As applyBottomUp
, but applies both functions whereever it can in the
data structure. It is very important that sA
is not the same type as
sB
-- odd results will occur if they are the same type. It is perfectly
valid for sA
to contain sB
or vice versa; in this case, the smaller
type will be processed first (as this is a bottom-up traversal) and the
larger type processed later on in the ascent (towards the root) of the
tree.
applyBottomUpA2 :: (AlloyA t (TwoOpA sA sB) BaseOpA, AlloyA sA BaseOpA (TwoOpA sA sB), AlloyA sB BaseOpA (TwoOpA sA sB), Applicative f) => f (sA -> sA) -> f (sB -> sB) -> t -> f t Source
applyBottomUpM2 :: (AlloyA t (TwoOpA sA sB) BaseOpA, AlloyA sA BaseOpA (TwoOpA sA sB), AlloyA sB BaseOpA (TwoOpA sA sB), Monad m) => (sA -> m sA) -> (sB -> m sB) -> t -> m t Source
applyBottomUpMRoute2 :: (AlloyARoute t (TwoOpARoute sA sB) BaseOpARoute, AlloyARoute sA BaseOpARoute (TwoOpARoute sA sB), AlloyARoute sB BaseOpARoute (TwoOpARoute sA sB), Monad m) => ((sA, Route sA t) -> m sA) -> ((sB, Route sB t) -> m sB) -> t -> m t Source
Listify functions that return lists of items that satisfy given criteria
listifyDepth :: (AlloyA t (OneOpA s) BaseOpA, AlloyA s BaseOpA (OneOpA s)) => (s -> Bool) -> t -> [s] Source
Given a function that examines a type s
and gives an answer (True to include
the item in the list, False to drop it), finds all items of type s
in some
larger item (of type t
) that satisfy this function, listed in depth-first
order.
listifyDepthRoute :: (AlloyARoute t (OneOpARoute s) BaseOpARoute, AlloyARoute s BaseOpARoute (OneOpARoute s)) => ((s, Route s t) -> Bool) -> t -> [(s, Route s t)] Source
Check functions to apply monadic checks throughout a data structure
checkDepthM :: (Monad m, AlloyA t (OneOpA s) BaseOpA, AlloyA s BaseOpA (OneOpA s)) => (s -> m ()) -> t -> m () Source
Given a monadic function that operates on items of type s
(without modifying
them), applies the function to all items of types s
within an item of type
t
, in depth-first order.
This can be used, for example, to perform checks on items in an error monad, or to accumulate information in a state monad, or to print out the structure in a writer or IO monad.
checkDepthM2 :: (Monad m, AlloyA t (TwoOpA r s) BaseOpA, AlloyA r BaseOpA (TwoOpA r s), AlloyA s BaseOpA (TwoOpA r s)) => (r -> m ()) -> (s -> m ()) -> t -> m () Source
Adding traversal to modifiers
makeBottomUp :: Alloy t BaseOp opT => opT -> (t -> t) -> t -> t Source
Given a set of operations and a modifier function, augments that modifier
function to first descend into the value before then applying the modifier function.
This can be used to perform a bottom-up depth-first traversal of a structure
(see the implementation of applyBottomUp
).
You are unlikely to need these functions much yourself; either use applyBottomUp
and similar to apply a function everywhere, or if you need more fine-grained
control over the descent, it is usually better to handle the descent in your
own functions.
makeBottomUpA :: (AlloyA t BaseOpA opT, Applicative f) => opT f -> f (t -> t) -> t -> f t Source
makeBottomUpM :: (AlloyA t BaseOpA opT, Monad m) => opT m -> (t -> m t) -> t -> m t Source
makeBottomUpMRoute :: (Monad m, AlloyARoute t BaseOpARoute opT) => opT m outer -> ((t, Route t outer) -> m t) -> (t, Route t outer) -> m t Source