-- Hoogle documentation, generated by Haddock
-- See Hoogle, http://www.haskell.org/hoogle/


-- | Workflow patterns over a monad for thread state logging & recovery
--   
--   Transparent support for interruptible computations. A workflow can be
--   seen as a persistent thread that executes a monadic computation.
--   Therefore, it can be used in very time consuming computations such are
--   CPU intensive calculations or procedures that are most of the time
--   waiting for the action of a process or an user, that are prone to
--   communication failures, timeouts or shutdowns. It also can be used if
--   you like to restart your program at the point where the user left it
--   last time . . The computation can be restarted at the interrupted
--   point thanks to its logged state in permanent storage. The thread
--   state is located in files by default. It can be moved and continued in
--   another computer. Besides that, the package also provides other higher
--   level services associated to workflows: Workflow patterns, and a
--   general configuration utility, workflow observation events and
--   references to the internal state. The state can be stored maintaining
--   memory references (using the <a>RefSerialize</a> package), so that it
--   is possible to track the modifications of a big structure (for example
--   a document) along the workflow execution.
--   
--   See <a>Control.Workflow</a> for details
--   
--   In this release: * Adaptation for MonadMask instance introduced in the
--   package exceptions-0.6
@package Workflow
@version 0.8.3

module Control.Workflow.Stat
data WF s m l
WF :: (s -> m (s, l)) -> WF s m l
[st] :: WF s m l -> s -> m (s, l)
data Stat
Running :: (Map String (String, Maybe ThreadId)) -> Stat
Stat :: DBRef Stat -> String -> Int -> Bool -> Maybe Integer -> Integer -> (Context, ByteString) -> [(Int, (IDynamic, Bool))] -> [IDynamic] -> Stat
[self] :: Stat -> DBRef Stat
[wfName] :: Stat -> String
[state] :: Stat -> Int
[recover] :: Stat -> Bool
[timeout] :: Stat -> Maybe Integer
[lastActive] :: Stat -> Integer
[context] :: Stat -> (Context, ByteString)
[references] :: Stat -> [(Int, (IDynamic, Bool))]
[versions] :: Stat -> [IDynamic]
stat0 :: Stat
statPrefix1 :: [Char]
statPrefix :: [Char]
header :: Stat -> STW ()
getHeader :: STR (String, Int, Maybe Integer, Integer, [t], (HashTable RealWorld Int (StableName MFun, MFun, [ShowF], Int), ByteString))
lenLen :: Int64

-- | Return the unique name of a workflow with a parameter (executed with
--   exec or start)
keyWF :: Indexable a => String -> a -> String
data WFRef a
WFRef :: !Int -> !(DBRef Stat) -> WFRef a
pathWFlows :: [Char]
stFName :: IResource a => a -> [Char]
fr :: Key -> IO (Maybe ByteString)
safe :: FilePath -> (Handle -> IO a) -> IO a
hReadFile :: Handle -> IO ByteString
readHeader :: ByteString -> Handle -> IO (Maybe (String, Int, Maybe Integer, Integer, [t], (HashTable RealWorld Int (StableName MFun, MFun, [ShowF], Int), ByteString)))
keyRunning :: String

-- | show the state changes along the workflow, that is, all the
--   intermediate results
showHistory :: Stat -> ByteString
showp1 :: IDynamic -> STW ()
wFRefStr :: [Char]

-- | default instances
instance GHC.Read.Read (Control.Workflow.Stat.WFRef a)
instance GHC.Show.Show (Control.Workflow.Stat.WFRef a)
instance Data.RefSerialize.Serialize Control.Workflow.Stat.Stat
instance Data.TCache.Defs.Indexable (Control.Workflow.Stat.WFRef a)
instance Data.TCache.IResource.IResource Control.Workflow.Stat.Stat
instance Data.RefSerialize.Serialize GHC.Conc.Sync.ThreadId
instance (GHC.Show.Show a, GHC.Read.Read a) => Data.RefSerialize.Serialize a
instance Data.RefSerialize.Serialize (Control.Workflow.Stat.WFRef a)


-- | A workflow can be seen as a persistent thread. The workflow monad
--   writes a log that permit to restore the thread at the interrupted
--   point. <a>step</a> is the (partial) monad transformer for the Workflow
--   monad. A workflow is defined by its name and, optionally by the key of
--   the single parameter passed. There primitives for starting workflows
--   also restart the interrupted workflow when it has been in execution
--   previously.
--   
--   A small example that print the sequence of integers in te console if
--   you interrupt the progam, when restarted again, it will start from the
--   last printed number
--   
--   <pre>
--   module Main where
--   import Control.Workflow
--   import Control.Concurrent(threadDelay)
--   import System.IO (hFlush,stdout)
--   
--   mcount n= do <a>step</a> $  do
--                          putStr (show n ++ " ")
--                          hFlush stdout
--                          threadDelay 1000000
--                mcount (n+1)
--                return () -- to disambiguate the return type
--   
--   main= <a>exec1</a>  "count"  $ mcount (0 :: Int)
--   </pre>
--   
--   <pre>
--   &gt;&gt;&gt; runghc demos\sequence.hs
--   &gt;0 1 2 3
--   &gt;CTRL-C Pressed
--   
--   &gt;&gt;&gt; runghc demos\sequence.hs
--   &gt;3 4 5 6 7
--   &gt;CTRL-C Pressed
--   
--   &gt;&gt;&gt; runghc demos\sequence.hs
--   &gt;7 8 9 10 11
--   ...
--   </pre>
--   
--   The program restart at the last saved step.
--   
--   As you can see, some side effect can be re-executed after recovery if
--   the log is not complete. This may happen after an unexpected shutdown
--   (in this case) or due to an asynchronous log writing policy. (see
--   <a>syncWrite</a>)
--   
--   When the step results are big and complex, use the
--   <a>Data.RefSerialize</a> package to define the (de)serialization
--   instances The log size will be reduced. showHistory` method will print
--   the structure changes in each step.
--   
--   If instead of <tt>RefSerialize</tt>, you use read and show instances,
--   there will be no reduction. but still it will work, and the log will
--   be readable for debugging purposes. The RefSerialize istance is
--   automatically derived from Read, Show instances.
--   
--   Data.Binary instances are also fine for serialization. To use Binary,
--   just define a binary instance of your data by using <a>showpBinary</a>
--   and <a>readpBinary</a>.
--   
--   Within the RefSerialize instance of a structure, you can freely mix
--   Show,Read RefSerialize and Data Binary instances.
--   
--   <a>Control.Workflow.Patterns</a> contains higher level workflow
--   patterns for handling multiple workflows
--   
--   <a>Control.Workflow.Configuration</a> permits the use of workflows for
--   configuration purposes
module Control.Workflow
data Stat
type Workflow m = WF Stat m
type WorkflowList m a b = Map String (a -> Workflow m b)

-- | <tt>PMonadTrans</tt> permits |to define a partial monad transformer.
--   They are not defined for all kinds of data but the ones that have
--   instances of certain classes.That is because in the lift instance code
--   there are some hidden use of these classes. This also may permit an
--   accurate control of effects. An instance of MonadTrans is an instance
--   of PMonadTrans
class PMonadTrans t m a
plift :: (PMonadTrans t m a, Monad m) => m a -> t m a

-- | Adapted from the <tt>MonadCatchIO-mtl</tt> package. However, in this
--   case it is needed to express serializable constraints about the
--   returned values, so the usual class definitions for lifting IO
--   functions are not suitable.
class MonadCatchIO m a

-- | Generalized version of <a>catch</a>
catch :: (MonadCatchIO m a, Exception e) => m a -> (e -> m a) -> m a

-- | Generalized version of <a>block</a>
block :: MonadCatchIO m a => m a -> m a

-- | Generalized version of <a>unblock</a>
unblock :: MonadCatchIO m a => m a -> m a
class MonadIO io => HasFork io
fork :: HasFork io => io () -> io ThreadId

-- | Generalized version of <a>throwIO</a>
throw :: (MonadIO m, Exception e) => e -> m a

-- | Indexable is an utility class used to derive instances of IResource
--   
--   Example:
--   
--   <pre>
--   data Person= Person{ pname :: String, cars :: [DBRef Car]} deriving (Show, Read, Typeable)
--   data Car= Car{owner :: DBRef Person , cname:: String} deriving (Show, Read, Eq, Typeable)
--   </pre>
--   
--   Since Person and Car are instances of <a>Read</a> ans <a>Show</a>, by
--   defining the <a>Indexable</a> instance will implicitly define the
--   IResource instance for file persistence:
--   
--   <pre>
--   instance Indexable Person where  key Person{pname=n} = "Person " ++ n
--   instance Indexable Car where key Car{cname= n} = "Car " ++ n
--   </pre>
class Indexable a
key :: Indexable a => a -> String
defPath :: Indexable a => a -> String

-- | Return the unique name of a workflow with a parameter (executed with
--   exec or start)
keyWF :: Indexable a => String -> a -> String

-- | Start or continue a workflow . <a>WFErrors</a> and exceptions are
--   returned as <tt>Left err</tt> (even if they were triggered as
--   exceptions). Other exceptions are returned as <tt>Left (Exception
--   e)</tt> use <a>killWF</a> or <a>delWF</a> in case of error to clear
--   the log.
start :: (MonadCatch m, MonadIO m, Indexable a, Serialize a, Typeable a) => String -> (a -> Workflow m b) -> a -> m (Either WFErrors b)

-- | Start or continue a workflow with exception handling the workflow
--   flags are updated even in case of exception <tt>WFerrors</tt> are
--   raised as exceptions
exec :: (Indexable a, Serialize a, Typeable a, Monad m, MonadIO m, MonadCatch m) => String -> (a -> Workflow m b) -> a -> m b

-- | A version of exec1 that deletes its state after complete execution or
--   thread killed
exec1d :: (MonadIO m, MonadCatch m) => String -> (Workflow m b) -> m b

-- | A version of exec with no seed parameter.
exec1 :: (Monad m, MonadIO m, MonadCatch m) => String -> Workflow m a -> m a

-- | executes a workflow, but does not mark it as finished even if the
--   process ended. It this case, the workflow just will return the last
--   result. If the workflow was gathering data from user questions for a
--   configuration, then this primitive will store them in the log the
--   first time, and can be retrieve it the next time.
exec1nc :: (Monad m, MonadIO m, MonadMask m) => String -> Workflow m a -> m a

-- | Start or restart an anonymous workflow inside another workflow. Its
--   state is deleted when finished and the result is stored in the
--   parent's WF state.
wfExec :: (Serialize a, Typeable a, MonadCatch m, MonadIO m) => Workflow m a -> Workflow m a

-- | Start or continue a workflow from a list of workflows with exception
--   handling. see <a>start</a> for details about exception and error
--   handling
startWF :: (MonadCatch m, MonadIO m, Serialize a, Serialize b, Typeable a, Indexable a) => String -> a -> WorkflowList m a b -> m (Either WFErrors b)

-- | Re-start the non finished workflows in the list, for all the initial
--   values that they may have been invoked. The list contain he
--   identifiers of the workflows and the procedures to be called. All the
--   workflows initiated with exec* or start* will be restarted with all
--   possible seed values.
restartWorkflows :: (Serialize a, Typeable a) => Map String (a -> Workflow IO b) -> IO ()

-- | Return conditions from the invocation of start/restart primitives
data WFErrors
NotFound :: WFErrors
AlreadyRunning :: WFErrors
Timeout :: WFErrors
WFException :: String -> WFErrors

-- | Lifts a monadic computation to the WF monad, and provides transparent
--   state loging and resuming the computation Note: Side effect can be
--   repeated at recovery time if the log was not complete before shut down
--   see the integer sequence example, above.
step :: (MonadIO m, Serialize a, Typeable a) => m a -> Workflow m a
getWFStat :: Monad m => Workflow m (DBRef Stat)
stepExec :: (Typeable t, Serialize t, MonadIO m) => DBRef Stat -> m t -> m (DBRef Stat, t)

-- | Executes a computation inside of the workflow monad whatever the monad
--   encapsulated in the workflow. Warning: this computation is executed
--   whenever the workflow restarts, no matter if it has been already
--   executed previously. This is useful for intializations or debugging.
--   To avoid re-execution when restarting use: <tt><a>step</a> $
--   unsafeIOtoWF...</tt>
--   
--   To perform IO actions in a workflow that encapsulates an IO monad, use
--   step over the IO action directly:
--   
--   <pre>
--   <a>step</a> $ action
--   </pre>
--   
--   instead of
--   
--   <pre>
--   <a>step</a> $ unsafeIOtoWF $ action
--   </pre>
unsafeIOtoWF :: (Monad m) => IO a -> Workflow m a
data WFRef a

-- | Log a value in the workflow log and return a reference to it.
--   
--   <pre>
--   newWFRef x= <a>stepWFRef</a> (return  x) &gt;&gt;= return . fst
--   </pre>
newWFRef :: (Serialize a, Typeable a, MonadIO m, MonadCatch m) => a -> Workflow m (WFRef a)

-- | Execute an step and return a reference to the result besides the
--   result itself
stepWFRef :: (Serialize a, Typeable a, MonadIO m) => m a -> Workflow m (WFRef a, a)

-- | Read the content of a Workflow reference. Note that its result is not
--   in the Workflow monad
readWFRef :: (Serialize a, Typeable a) => WFRef a -> STM (Maybe a)

-- | Writes a new value en in the workflow reference, that is, in the
--   workflow log. Why would you use this?. Don't do that!. modifiying the
--   content of the workflow log would change the excution flow when the
--   workflow restarts. This metod is used internally in the package. The
--   best way to communicate with a workflow is trough a persistent queue,
--   using <a>Data.Persistent.Collection</a>:
--   
--   <pre>
--   worflow= exec1 "wf" do
--            r &lt;- <a>stepWFRef</a>  expr
--            <tt>push</tt> "queue" r
--            back &lt;- <tt>pop</tt> "queueback"
--            ...
--   </pre>
writeWFRef :: (Serialize a, Typeable a) => WFRef a -> a -> STM ()

-- | Moves the state of workflow with a seed value to become the state of
--   other seed value This may be of interest when the entry value changes
--   its key value but should not initiate a new workflow but continues
--   with the current one
moveState :: (MonadIO m, Indexable a, Serialize a, Typeable a) => String -> a -> a -> m ()

-- | wait until the workflow is restarted
waitWFActive :: String -> STM ()

-- | Return all the steps of the workflow log. The values are dynamic
--   
--   to get all the steps with result of type Int: <tt>all &lt;-
--   <a>getAll</a> let lfacts = mapMaybe <a>safeFromIDyn</a> all ::
--   [Int]</tt>
getAll :: Monad m => Workflow m [IDynamic]
safeFromIDyn :: (Typeable * a, Serialize a) => IDynamic -> Either String a

-- | Return the keys of the workflows that are running with a given prefix
getWFKeys :: String -> IO [String]

-- | Return the current state of the computation, in the IO monad
getWFHistory :: (Indexable a, Serialize a) => String -> a -> IO (Maybe Stat)

-- | Observe the workflow log until a condition is met.
waitFor :: (Indexable a, Serialize a, Serialize b, Typeable a, Indexable b, Typeable b) => (b -> Bool) -> String -> a -> IO b
waitForSTM :: (Indexable a, Serialize a, Serialize b, Typeable a, Indexable b, Typeable b) => (b -> Bool) -> String -> a -> STM b

-- | Wait until a certain clock time has passed by monitoring its flag, in
--   the STM monad. This permits to compose timeouts with locks waiting for
--   data using <a>orElse</a>
--   
--   <ul>
--   <li>example: wait for any respoinse from a Queue if no response is
--   given in 5 minutes, it is returned True.</li>
--   </ul>
--   
--   <pre>
--   flag &lt;- <a>getTimeoutFlag</a> $  5 * 60
--   ap   &lt;- <a>step</a>  .  atomically $  readSomewhere &gt;&gt;= return . Just  <a>orElse</a>  <a>waitUntilSTM</a> flag  &gt;&gt; return Nothing
--   case ap of
--        Nothing -&gt; do <a>logWF</a> "timeout" ...
--        Just x -&gt; do <a>logWF</a> $ "received" ++ show x ...
--   
--   </pre>
waitUntilSTM :: TVar Bool -> STM ()

-- | Start the timeout and return the flag to be monitored by
--   <a>waitUntilSTM</a> This timeout is persistent. This means that the
--   counter is initialized in the first call to getTimeoutFlag no matter
--   if the workflow is restarted. The time during which the worlkflow has
--   been stopped count also. Thus, the wait time can exceed the time
--   between failures. when timeout is 0 means no timeout.
getTimeoutFlag :: MonadIO m => Integer -> Workflow m (TVar Bool)

-- | Return either the result of the STM conputation or Nothing in case of
--   timeout. The computation can retry This timeout is persistent. This
--   means that the counter is initialized in the first call to
--   getTimeoutFlag no matter if the workflow is restarted. The time during
--   which the worlkflow has been stopped count also. Thus, the wait time
--   can exceed the time between failures. when timeout is 0 it means no
--   timeout.
withTimeout :: (MonadIO m, Typeable a, Serialize a) => Integer -> STM a -> Workflow m (Maybe a)

-- | Executes a computation understanding that it is inside the workflow
--   identified by <a>id</a>. If <tt>f</tt> finish after <tt>time</tt> it
--   genetates a <a>Timeout</a> exception which may result in the end of
--   the workflow if the programmer does not catch it. If the workflow is
--   restarted after <tt>time2</tt> has elapsed, the workflow will restart
--   from the beginning. If not, it will restart after the last logged
--   step.
--   
--   Usually <tt>time2&gt; time</tt>
--   
--   <tt>time2=0</tt> means <tt>time2</tt> is infinite withKillTimeout ::
--   CMC.MonadCatchIO m =&gt; String -&gt; Int -&gt; Integer -&gt; m a
--   -&gt; m a withKillTimeout id time time2 f = do tid &lt;- liftIO
--   myThreadId tstart &lt;- liftIO getTimeSeconds let final= liftIO $ do
--   tnow &lt;- getTimeSeconds let ref = getDBRef $ keyResource $
--   stat0{wfName=id} -- !&gt; (keyResource $ stat0{wfName=id} ) when
--   (time2 /=0) . atomically $ do s &lt;- readDBRef ref <a>onNothing</a>
--   error ( "withKillTimeout: Workflow not found: "++ id) writeDBRef ref
--   s{lastActive= tnow,timeout= Just (time2 - fromIntegral (tnow -
--   tstart))} clearRunningFlag id let proc= do twatchdog &lt;- liftIO $
--   case time of 0 -&gt; return tid _ -&gt; forkIO $ threadDelay (time *
--   1000000) &gt;&gt; throwTo tid Timeout r &lt;- f liftIO $ killThread
--   twatchdog return r
--   
--   proc <a>finally</a> final
withKillTimeout :: (MonadIO m, MonadCatch m) => String -> Int -> Integer -> m a -> m a

-- | Log a message in the workflow history. I can be printed out with
--   <a>showHistory</a> The message is printed in the standard output too
logWF :: MonadIO m => String -> Workflow m ()
clearRunningFlag :: MonadIO m => [Char] -> m (Map String (String, Maybe ThreadId), Maybe ThreadId)

-- | Kill the executing thread if not killed, but not its state.
--   <a>exec</a> <a>start</a> or <a>restartWorkflows</a> will continue the
--   workflow
killThreadWF :: (Indexable a, Serialize a, Typeable a, MonadIO m) => String -> a -> m ()

-- | Kill the process (if running) and drop it from the list of
--   restart-able workflows. Its state history remains , so it can be
--   inspected with <tt>getWfHistory</tt> <a>showHistory</a> and so on.
--   
--   When the workflow has been called with no parameter, use: ()
killWF :: (Indexable a, MonadIO m) => String -> a -> m ()

-- | Delete the WF from the running list and delete the workflow state from
--   persistent storage. Use it to perform cleanup if the process has been
--   killed.
--   
--   When the workflow has been called with no parameter, use: ()
delWF :: (Indexable a, MonadIO m, Typeable a) => String -> a -> m ()

-- | A version of <tt>KillThreadWF</tt> for workflows started wit no
--   parameter by <a>exec1</a>
killThreadWF1 :: MonadIO m => String -> m ()

-- | Delete the history of a workflow. Be sure that this WF has finished.
delWFHistory :: Indexable t => String -> t -> IO ()
delWFHistory1 :: String -> IO ()

-- | Specify the cache synchronization policy with permanent storage. See
--   <a>SyncMode</a> for details
syncWrite :: SyncMode -> IO ()
data SyncMode :: *

-- | sync state to permanent storage when <a>atomicallySync</a> is invoked
Synchronous :: SyncMode
Asyncronous :: Int -> (Integer -> Integer -> Integer -> Bool) -> Int -> SyncMode

-- | number of seconds between saves when asyncronous
[frecuency] :: SyncMode -> Int

-- | The user-defined check-for-cleanup-from-cache for each object.
--   <a>defaultCheck</a> is an example
[check] :: SyncMode -> Integer -> Integer -> Integer -> Bool

-- | size of the cache when async
[cacheSize] :: SyncMode -> Int

-- | use <a>syncCache</a> to write the state
SyncManual :: SyncMode

-- | show the state changes along the workflow, that is, all the
--   intermediate results
showHistory :: Stat -> ByteString

-- | True if the workflow in recovery mode, reading the log to recover the
--   process state
isInRecover :: Monad m => Workflow m Bool
runWF1 :: MonadIO m => String -> WF Stat m b -> Stat -> Bool -> m b
getState :: (Monad m, MonadIO m, Indexable a, Serialize a, Typeable a) => String -> x -> a -> m (Either WFErrors (String, x, Stat))
instance GHC.Show.Show Control.Workflow.WFInfo
instance GHC.Read.Read Control.Workflow.WFInfo
instance GHC.Show.Show Control.Workflow.WFErrors
instance GHC.Read.Read Control.Workflow.WFErrors
instance GHC.Base.Monad m => GHC.Base.Monad (Control.Workflow.Stat.WF s m)
instance (GHC.Base.Monad m, GHC.Base.Functor m) => GHC.Base.Functor (Control.Workflow.Stat.WF s m)
instance (GHC.Base.Monad m, Control.Monad.IO.Class.MonadIO m, Data.RefSerialize.Serialize a, Data.Typeable.Internal.Typeable a) => Control.Workflow.PMonadTrans (Control.Workflow.Stat.WF Control.Workflow.Stat.Stat) m a
instance (GHC.Base.Monad m, GHC.Base.Functor m) => GHC.Base.Applicative (Control.Workflow.Stat.WF s m)
instance (Control.Monad.Trans.Class.MonadTrans t, GHC.Base.Monad m) => Control.Workflow.PMonadTrans t m a
instance Control.Monad.IO.Class.MonadIO m => Control.Monad.IO.Class.MonadIO (Control.Workflow.Stat.WF Control.Workflow.Stat.Stat m)
instance Control.Workflow.HasFork GHC.Types.IO
instance (Control.Workflow.HasFork io, Control.Monad.IO.Class.MonadIO io, Control.Monad.Catch.MonadCatch io) => Control.Workflow.HasFork (Control.Workflow.Stat.WF Control.Workflow.Stat.Stat io)
instance GHC.Exception.Exception Control.Workflow.WFErrors


-- | Helpers for application initialization
module Control.Workflow.Configuration

-- | to execute one computation once . It executes at the first run only
once :: (Typeable a, Serialize a, MonadIO m) => m a -> Workflow m a

-- | to execute a computation every time it is invoked. A synonimous of
--   <a>unsafeIOtoWF</a>
ever :: (Typeable a, Serialize a, MonadIO m) => IO a -> Workflow m a

-- | executes a computation with <a>once</a> and <a>ever</a> statements a
--   synonym of <a>exec1nc</a>
runConfiguration :: (Monad m, MonadIO m, MonadMask m) => String -> Workflow m a -> m a


-- | This module contains monadic combinators that express some workflow
--   patterns. see the docAprobal.hs example included in the package
--   
--   EXAMPLE:
--   
--   This fragment below describes the approbal procedure of a document.
--   First the document reference is sent to a list of bosses trough a
--   queue. ithey return a boolean in a return queue ( askUser) the
--   booleans are summed up according with a monoid instance (sumUp)
--   
--   if the resullt is false, the correctWF workflow is executed If the
--   result is True, the pipeline continues to the next stage
--   (<tt>checkValidated</tt>)
--   
--   the next stage is the same process with a new list of users
--   (superbosses). There is a timeout of seven days. The result of the
--   users that voted is summed up according with the same monoid instance
--   
--   if the result is true the document is added to the persistent list of
--   approbed documents if the result is false, the document is added to
--   the persistent list of rejectec documents (<tt>checlkValidated1</tt>)
--   
--   The program can be interrupted at any moment. The Workflow monad will
--   restartWorkflows it at the point where it was interrupted.
--   
--   This example uses queues from <a>Data.Persistent.Queue</a>
--   
--   @docApprobal :: Document -&gt; Workflow IO () docApprobal doc =
--   <tt>getWFRef</tt> &gt;&gt;= docApprobal1
--   
--   docApprobal1 rdoc= return True &gt;&gt;= log "requesting approbal from
--   bosses" &gt;&gt;= <a>sumUp</a> 0 (map (askUser doc rdoc) bosses)
--   &gt;&gt;= checkValidated &gt;&gt;= log "requesting approbal from
--   superbosses or timeout" &gt;&gt;= <a>sumUp</a> (7*60*60*24)
--   (map(askUser doc rdoc) superbosses) &gt;&gt;= checkValidated1
--   
--   askUser _ _ user False = return False askUser doc rdoc user True = do
--   <a>step</a> $ <tt>push</tt> (quser user) rdoc <a>logWF</a> ("wait for
--   any response from the user: " ++ user) <a>step</a> . <tt>pop</tt> $
--   qdocApprobal (title doc)
--   
--   log txt x = <a>logWF</a> txt &gt;&gt; return x
--   
--   checkValidated :: Bool -&gt; <a>Workflow</a> IO Bool checkValidated
--   val = case val of False -&gt; correctWF (title doc) rdoc &gt;&gt;
--   return False _ -&gt; return True
--   
--   checkValidated1 :: Bool -&gt; Workflow IO () checkValidated1 val =
--   step $ do case val of False -&gt; <tt>push</tt> qrejected doc _ -&gt;
--   <tt>push</tt> qapproved doc mapM (u -&gt;deleteFromQueue (quser u)
--   rdoc) superbosses@
module Control.Workflow.Patterns

-- | spawn a list of independent workflow <tt>actions</tt> with a seed
--   value <tt>a</tt> The results are reduced by <a>merge</a> or
--   <a>select</a>
split :: (Typeable b, Serialize b, HasFork io, MonadMask io) => [a -> Workflow io b] -> a -> Workflow io [ActionWF b]

-- | wait for the results and apply the cond to produce a single output in
--   the Workflow monad
merge :: (MonadIO io, Typeable a, Typeable b, Serialize a, Serialize b) => ([a] -> io b) -> [ActionWF a] -> Workflow io b

-- | select the outputs of the workflows produced by <a>split</a>
--   constrained within a timeout. The check filter, can select , discard
--   or finish the entire computation before the timeout is reached. When
--   the computation finalizes, it kill all the pending workflows and
--   return the list of selected outputs the timeout is in seconds and it
--   is is in the workflow monad, so it is possible to restart the process
--   if interrupted, so it can proceed for years.
--   
--   This is necessary for the modelization of real-life institutional
--   cycles such are political elections A timeout of 0 means no timeout.
select :: (Serialize a, Typeable a, HasFork io, MonadMask io) => Integer -> (a -> STM Select) -> [ActionWF a] -> Workflow io [a]

-- | spawn a list of workflows and reduces the results according with the
--   <tt>comp</tt> parameter within a given timeout
--   
--   <pre>
--   vote timeout actions comp x=
--        split actions x &gt;&gt;= select timeout (const $ return Select)  &gt;&gt;=  comp
--   </pre>
vote :: (Serialize b, Typeable b, HasFork io, MonadMask io) => Integer -> [a -> Workflow io b] -> ([b] -> Workflow io c) -> a -> Workflow io c

-- | sum the outputs of a list of workflows according with its monoid
--   definition
--   
--   <pre>
--   sumUp timeout actions = vote timeout actions (return . mconcat)
--   </pre>
sumUp :: (Serialize b, Typeable b, Monoid b, HasFork io, MonadMask io) => Integer -> [a -> Workflow io b] -> a -> Workflow io b
data Select

-- | select the source output
Select :: Select

-- | Discard the source output
Discard :: Select

-- | Continue the source process
Continue :: Select

-- | Discard this output, kill all and return the selected outputs
FinishDiscard :: Select

-- | Select this output, kill all and return the selected outputs
FinishSelect :: Select
instance GHC.Show.Show Control.Workflow.Patterns.Select
instance GHC.Read.Read Control.Workflow.Patterns.Select
instance GHC.Exception.Exception Control.Workflow.Patterns.Select
