Safe Haskell | None |
---|---|
Language | Haskell2010 |
Hyperion.Concurrent
Description
This module contains copies of several utilities from
Control.Concurrent.Async from the async
package, with IO
replaced by Process
.
Synopsis
- race :: Process a -> Process b -> Process (Either a b)
- concurrently :: Process a -> Process b -> Process (a, b)
- concurrently' :: Process a -> Process b -> (MVar (Either SomeException (Either a b)) -> Process r) -> Process r
- newtype Concurrently m a = Concurrently {
- runConcurrently :: m a
- doConcurrently :: (Applicative (Concurrently m), Traversable t) => t (m a) -> m (t a)
- doConcurrently_ :: (Applicative (Concurrently m), Foldable t, Functor t) => t (m a) -> m ()
- mapConcurrently :: (Applicative (Concurrently m), Traversable t) => (a -> m b) -> t a -> m (t b)
- mapConcurrently_ :: (Applicative (Concurrently m), Foldable t, Functor t) => (a -> m b) -> t a -> m ()
- forConcurrently :: (Applicative (Concurrently m), Traversable t) => t a -> (a -> m b) -> m (t b)
- forConcurrently_ :: (Applicative (Concurrently m), Foldable t, Functor t) => t a -> (a -> m b) -> m ()
- replicateConcurrently :: Applicative (Concurrently m) => Int -> m a -> m [a]
- replicateConcurrently_ :: Applicative (Concurrently m) => Int -> m a -> m ()
Documentation
race :: Process a -> Process b -> Process (Either a b) Source #
Runs the two Process
es concurrently and returns the first available result,
kill
ing the unfinished process. If any of the processes throw an exception,
the processes are kill
ed and the exception is propagated out of race
.
concurrently :: Process a -> Process b -> Process (a, b) Source #
Runs the two Process
es concurrently and returns both results. If any of the
processes throw an exception, the processes are kill
ed and the
exception is propagated out of concurrently
.
concurrently' :: Process a -> Process b -> (MVar (Either SomeException (Either a b)) -> Process r) -> Process r Source #
Runs two Process
es concurrently in two new threads. Each process will
compute the result and putMVar
it into an MVar
. The user-supplied
continuation is applied to this MVar
concurrently with the two threads.
When the continuation returns a result, the new threads are kill
ed and the
result is returned from concurrently'
. If a thread fails, the MVar
is
filled with Left
SomeException
.
Note that the continutation can inspect the results of both threads by emptying
the MVar
when appropriate.
TODO: This code was originally copied from the
Control.Concurrent.Async module, with forkIO
replaced by
spawnLocal
. As of async-2.1
, the code for this function has
changed. Have a look and figure out why, and whether the changes
should be ported here?
Concurrently
type
represents a computation of type Concurrently
m am a
that
can be run concurrently with other Concurrently
-type
computations. It is essentially a copy of the Concurrently
applicative from Control.Concurrent.Async, with IO
replaced by
Process
.
Concurrently
is an instance of several type classes (see below), but
most notable are the instances of Applicative
and Alternative
.
The instances we define are for
,
which in practice means Concurrently
(ReaderT
r Process
)
and
Concurrently
Cluster
.Concurrently
Job
Applicative
instance
The Applicative
instance defines for f ::
and
Concurrently
m (a->b)x ::
computationsConcurrently
m a
f <*> x
to be the 'Concurrently m b' computation which is peformed as follows:
first, f
and x
are computed concurrently using concurrently
, yielding values of the types
a->b
and a
. Then these values are combined in the obvious way into a value
of type b
. The implementation of
is simply the computation which
returns pure
xx
.
In this way, we can define, for example,
doConcurrently' :: [ Concurrently m a ] -> Concurrently m [a] doConcurrenlty' [] = pure [] doConcurrenlty' (x:xs) = pure (:) <*> x <*> doConcurrently' xs
which takes a list of computations and returns a computation that performs these computations concurrently and combines their results into a list.
This definition of doConcurrently'
works in the following way. The first line
is the base for our recursive definition -- an empty list is a trivial computation.
The second line will first compute
-- this is a rather trivial
concurrent computation that returns the function pure
(:)
. We combine this
calcuation with (:)
x
using <*>
, which makes it into a calculation that computes
the function (:) x'
, i.e. the function that prepends x'
to a list. Here
x'
is the result of the calculation x
. Then we combine this calculation
with doConcurrently' xs
, which means that we compute (:) x'
concurrently
with doConcurrently' xs
, and then combine the results. The result of
doConcurrently' xs
will be a list of values, and we prepend x'
to it.
Recursing into doConcurrently' xs
we see that doConcurrently'
indeed works
by taking a list of computations, performing the calcuations concurrently, and
returning the list of results.
We can also define a more convenient function doConcurrently
as follows
doConcurrently :: [ m a ] -> m [a] doConcurrently xs = runConcurrently $ doConcurrently' $ map Concurrently xs
which works by dressing m a
in the list in Concurrently
, performing
doConcurrently'
and then finally removing the Concurrently
constructor using
runConcurrently
. The actual definition of doConcurrently
is more general,
so that it works on any Traversable
instance, not just on lists.
Alternative
instance
The Alternative
instance of Concurrenlty
is similar, except it uses
race
instead of concurrenlty
. Specifically,
a <|> b
performs the computations a
and b
concurrently and returns the result of
whichever finishes earlier, using race
. The empty
implementation is a
computation which never returns. In particular,
empty <|> empty
never returns (so is the same as empty
, to some extent). We can do, for example
asum [ x, y, z ]
which will run x
, y
, and z
concurrently and return the first returned
result, kill
ing the unfinished computations.
newtype Concurrently m a Source #
Constructors
Concurrently | |
Fields
|
Instances
Utility functions using Applicative
instance of Concurrently
doConcurrently :: (Applicative (Concurrently m), Traversable t) => t (m a) -> m (t a) Source #
Run several computations in a traversable structure concurrently and collect the results.
doConcurrently_ :: (Applicative (Concurrently m), Foldable t, Functor t) => t (m a) -> m () Source #
Run several computations in a traversable structure concurrently and forget the results.
mapConcurrently :: (Applicative (Concurrently m), Traversable t) => (a -> m b) -> t a -> m (t b) Source #
Concurrently map a function over a traversable structure.
mapConcurrently_ :: (Applicative (Concurrently m), Foldable t, Functor t) => (a -> m b) -> t a -> m () Source #
Concurrently map a function over a traversable structure and forget the results.
forConcurrently :: (Applicative (Concurrently m), Traversable t) => t a -> (a -> m b) -> m (t b) Source #
Flipped version of mapConcurrently
.
forConcurrently_ :: (Applicative (Concurrently m), Foldable t, Functor t) => t a -> (a -> m b) -> m () Source #
Flipped version of mapConcurrently_
.
replicateConcurrently :: Applicative (Concurrently m) => Int -> m a -> m [a] Source #
Concurrently run n
copies of a computation and collect the results in a list.
replicateConcurrently_ :: Applicative (Concurrently m) => Int -> m a -> m () Source #
Concurrently run n
copies of a computation and forget the results.