Safe Haskell | None |
---|
- type Glance m l o a = o -> LogicT (Produ l (Nullipotent m)) a
- missing :: Monad m => Glance m l o a -> Glance m l o ()
- collect :: (Monad m, MonadPlus n) => Glance m l o a -> Glance m l o (n a)
- liftN :: Monad m => Glance m l (Nullipotent m a) a
- newtype Pianola m l o a = Pianola {}
- type Delay = Int
- pfail :: Monad m => Pianola m l o a
- pmaybe :: Monad m => Pianola m l o a -> Pianola m l o (Maybe a) -> Pianola m l o a
- peek :: Monad m => Glance m l o a -> Pianola m l o a
- peekMaybe :: Monad m => Glance m l o a -> Pianola m l o (Maybe a)
- retryPeek1s :: Monad m => Int -> Glance m l o a -> Pianola m l o (Maybe a)
- retryPeek :: Monad m => Pianola m l o u -> Int -> Glance m l o a -> Pianola m l o (Maybe a)
- poke :: Monad m => Glance m l o (Sealed m) -> Pianola m l o ()
- pokeMaybe :: Monad m => Glance m l o (Sealed m) -> Pianola m l o (Maybe ())
- retryPoke1s :: Monad m => Int -> Glance m l o (Sealed m) -> Pianola m l o (Maybe ())
- retryPoke :: Monad m => Pianola m l o u -> Int -> Glance m l o (Sealed m) -> Pianola m l o (Maybe ())
- sleep :: Monad m => Delay -> Pianola m l o ()
- with :: Monad m => Glance m l o' o -> Pianola m l o a -> Pianola m l o' a
- withMaybe :: Monad m => Glance m l o' o -> Pianola m l o a -> Pianola m l o' (Maybe a)
- withRetry1s :: Monad m => Int -> Glance m l o' o -> Pianola m l o a -> Pianola m l o' (Maybe a)
- withRetry :: Monad m => Pianola m l o' u -> Int -> Glance m l o' o -> Pianola m l o a -> Pianola m l o' (Maybe a)
- ralentize :: Delay -> Pianola m l o a -> Pianola m l o a
- ralentizeByTag :: ([Tag] -> Bool) -> Delay -> Pianola m l o a -> Pianola m l o a
- autolog :: Pianola m LogEntry o a -> Pianola m LogEntry o a
- play :: Monad m => m o -> Pianola m l o a -> Produ Delay (MaybeT (Produ l m)) a
Documentation
type Glance m l o a = o -> LogicT (Produ l (Nullipotent m)) aSource
A Glance is just a kleisli arrow used to locate and extract particular elements of type a in a data structure of type o.
The following effects are allowed:
- Nondeterminism and failure. A Glance can return more than one value (or zero
values, with
mzero
). See thereplusify
function, which is a valid Glance. - Logging. A Glance can log messages of type l about the elements it
encounters during search, even elements visited in search branches which
ultimately fail to produce any results. See
logmsg
. - Interactions with the server through the monad m, but only interactions
that don't change the state of the GUI. For example, getting a image capture
of a window. See
Nullipotent
.
The following effects are forbidden:
- Any kind of delay effect. Glances must return as soon as possible.
- Interactions with the server which do change the state of the GUI. Note
that you can target and return the actions of type
Sealed
which dangle on the branches of the source data structure. You just can't execute them inside a Glance. To actually execute them, pass the glance as an argument topoke
.
missing :: Monad m => Glance m l o a -> Glance m l o ()Source
When the Glance
passed as argument finds nothing, the returned glance
finds a single (). When the Glance passed as argument finds one or more
values, the returned Glance finds zero results.
This function can be used in combination with retryPeek1s
to wait for the
dissapearance of a component on screen.
collect :: (Monad m, MonadPlus n) => Glance m l o a -> Glance m l o (n a)Source
Takes all the values returned by a Glance
and returns a new Glance in
which those values have been collected in a MonadPlus
(often a list). This
is useful when we want to recover a list of components which meet certain
criteria in order to compare them among themselves. For example, getting all
the buttons present in a window and sorting them left to right by their
position on the screen.
liftN :: Monad m => Glance m l (Nullipotent m a) aSource
Executes a Nullipotent
action in the context of a Glance
.
newtype Pianola m l o a Source
A computation which interacts which an external system represented locally by the type o, using actions on the monad m, emitting log messages of type l, and returning a value of type a.
The following effects are allowed:
- Purely observational interactions with the external system. See
peek
. - Logging. Log messages are emitted in the middle of the computation, unlike
in a Writer monad. See
logmsg
andlogimg
. - Failure. See
pfail
. - Delays. See
sleep
. - Actions in the m monad which actually change the external system, like
clicking on a button of a GUI. See
poke
.
Instead of baking all possible effects into the base free monad, Pianola
takes the approach of representing each effect using the Proxy
type from
the pipes package.
The order of the trasformers in the monad stack is not arbitrary. For example: it does not make sense for a log message to make the computation fail or to trigger actions against the external system, so the log producer is colocated closest to the base monad, where it doesn't have access to those kind of effects.
Another example: it can be conveniento to automatically introduce a delay
after every action (see ralentize
) or to automatically log each action
(see autolog
). Therefore, the Sealed
action producer is in the
outermost position, having access to all the effects.
To actually execute a Pianola, use a driver function like
simpleDriver
or a specialization of it.
retryPeek1s :: Monad m => Int -> Glance m l o a -> Pianola m l o (Maybe a)Source
Like peekMaybe
, but the specified number of retries is performed before
returning Nothing. There is an sleep of 1 second between each retry.
retryPeek :: Monad m => Pianola m l o u -> Int -> Glance m l o a -> Pianola m l o (Maybe a)Source
A more general version of retryPeek1s
which intersperses any Pianola
action between retries.
poke :: Monad m => Glance m l o (Sealed m) -> Pianola m l o ()Source
Takes a glance that extracts an action of type Sealed
from a data
structure, and returns a Pianola
executing the action (when the Pianola is
interpreted by some driver-like fuction like
simpleDriver
.)
retryPoke1s :: Monad m => Int -> Glance m l o (Sealed m) -> Pianola m l o (Maybe ())Source
Like pokeMaybe
, but the specified number of retries is performed before
returning Nothing. There is an sleep of 1 second between each retry.
retryPoke :: Monad m => Pianola m l o u -> Int -> Glance m l o (Sealed m) -> Pianola m l o (Maybe ())Source
A more general version of retryPoke1s
which intersperses any Pianola
action between retries.
with :: Monad m => Glance m l o' o -> Pianola m l o a -> Pianola m l o' aSource
Expands the context of a Pianola
using a Glance
. Typical use: transform a Pianola whose context is a particular window to a Pianola whose context is the whole GUI, using a Glance which locates the window in the GUI.
with glance1 $ peek glance2
is equal to
peek $ glance1 >=> glance2
with
can be used to group peeks and pokes whose glances share part of thir paths in common:
do poke $ glance1 >=> glance2 poke $ glance1 >=> glance3
is equal to
with glance1 $ do poke glance2 poke glance3
withRetry1s :: Monad m => Int -> Glance m l o' o -> Pianola m l o a -> Pianola m l o' (Maybe a)Source
Like withMaybe
, but several attempts to locate the target of the glance
are performed, with a separation of 1 second.
withRetry :: Monad m => Pianola m l o' u -> Int -> Glance m l o' o -> Pianola m l o a -> Pianola m l o' (Maybe a)Source
ralentize :: Delay -> Pianola m l o a -> Pianola m l o aSource
Takes a delay in seconds and a Pianola
as parameters, and returns a
ralentized Pianola in which the delay has been inserted after every action.
autolog :: Pianola m LogEntry o a -> Pianola m LogEntry o aSource
Modifies a Pianola
so that the default tags associated to an action are
logged automatically when the action is executed.
play :: Monad m => m o -> Pianola m l o a -> Produ Delay (MaybeT (Produ l m)) aSource
Unwinds all the Glances contained in a Pianola
by supplying them with
the monadic value passed as the first argument. When a Glance
returns with
more than one result, one of the results is selected in order to continue (TO DO:
emit a warning when this happens). The log messages of the glances are
fused with the Pianola's own log stream. All the Sealed
actions are
injected into the base monad. The delay and log effects remain uninjected.
Usually, clients should not call this function directly, but use a
driver function like simpleDriver
.