>-- | One can 'send' a messages to a @Mailbox@ where it will be processed>-- according to an actor\'s defined 'Behavior'>newtypeMailboxa=Mailbox{inChan::InChana}>deriving(Contravariant)>

We don't need to expose this thanks to the miracle of MonadFix and recursive do,
but this can be generated via the NewSplitChan class below if the user imports
the library:

>newtypeMessagesa=Messages{outChan::OutChana}>deriving(Functor)>>-- Not sure how to derive this or if possible:>instanceSplitChanMailboxMessageswhere>readChan=readChan.outChan>writeChan=writeChan.inChan>writeList2Chan=writeList2Chan.inChan>>instanceNewSplitChanMailboxMessageswhere>newSplitChan=fmap(\(i,o)->(Mailboxi,Messageso))newSplitChan>

ACTIONS
=======
Functionality is based on our underlying type classes, but users shouldn't need
to import a bunch of libraries to get basic Behavior building functionality.

>infixl3<.|>

>-- | Sequence two @Behavior@s. After the first 'yield's the second takes over,>-- discarding the message the former was processing. See also the 'Monoid'>-- instance for @Behavior@.>-- >-- > b <.|> b' = b `mappend` constB b'>(<.|>)::Behaviori->Behaviori->Behaviori>b<.|>b'=b`mappend`constBb'

The 'yield' function is so named because it is "relinquishing control", i.e. I
think the name reminds of the functionality of and mappend (the last input
is passed along) and also has the meaning "quit".
Its similarity (or not) to the 'enumerator' function of the same same may be a
source of confusion (or the opposite)... I'm not sure.

>-- | Return the message received to start this 'Action' block. /N.B/ the value>-- returned here does not change between calls in the same 'Action'.>-->-- > received = ask>received::Actionii>received=ask

>-- | Send a message asynchronously. This can be used to send messages to other>-- Actors via a 'Mailbox', or used as a means of output from the Actor system>-- to IO since the function is polymorphic.>-- >-- > send b = liftIO . writeChan b>send::(MonadIOm,SplitChancx)=>ca->a->m()>sendb=liftIO.writeChanb

FORKING AND RUNNING ACTORS:
===========================

>-- | Like 'spawn' but allows one to specify explicitly the channel from which>-- an actor should take its input. Useful for extending the library to work>-- over other channels.>spawnReading::(MonadIOm,SplitChanxc)=>ci->Behaviori->m()>spawnReadingstr=liftIO.void.forkIO.actorRunner>whereactorRunnerb=>readChanstr>>=runBehaviorStepb>>=F.mapM_actorRunner

RUNNING ACTORS
--------------
These work in IO, returning () when the actor finishes with done/mzero:

>-- | Run a @Behavior ()@ in the main thread, returning when the computation>-- exits.>runBehavior_::Behavior()->IO()>runBehavior_b=runBehaviorb[(),()..]>>-- | run a 'Behavior' in the IO monad, taking its \"messages\" from the list.>runBehavior::Behaviora->[a]->IO()>runBehaviorb(a:as)=runBehaviorStepba>>=F.mapM_(`runBehavior`as)>runBehavior__=return()

FORKING ACTORS
--------------

>-- | Fork an actor performing the specified 'Behavior'. /N.B./ an actor >-- begins execution of its 'headBehavior' only after a mesage has been >-- received. See also 'spawn_'.>spawn::(MonadIOm)=>Behaviori->m(Mailboxi)>spawnb=do>(m,s)<-liftIOnewSplitChan>spawnReadingsb>returnm>>-- | Fork a looping computation which starts immediately. Equivalent to>-- launching a @Behavior ()@ and another 'Behavior' that sends an infinite stream of>-- ()s to the former\'s 'Mailbox'.>spawn_::(MonadIOm)=>Behavior()->m()>spawn_=liftIO.void.forkIO.runBehavior_

USEFUL GENERAL BEHAVIORS
========================

>-- | Prints all messages to STDOUT in the order they are received,>-- 'yield'-ing /immediately/ after @n@ inputs are printed.>printB::(Shows,Eqn,Numn)=>n->Behaviors>printB=contramap(unlines.return.show).putStrB

We want to yield right after printing the last input to print. This lets us
compose with signalB for instance:
write5ThenExit = putStrB 5 `mappend` signalB c
and the above will signal as soon as it has printed the last message. If we try
to define this in a more traditional recursive way the signal above would only
happen as soon as the sixth message was received.
For now we allow negative

>-- | Like 'printB' but using @putStr@.>putStrB::(Eqn,Numn)=>n->BehaviorString>putStrB0=mempty--special case when called directly w/ 0>putStrBn=Receive$do>s<-received>liftIO$putStrs>guard(n/=1)>return$putStrB(n-1)

>-- | Sends a @()@ to the passed chan. This is useful with 'mappend' for>-- signalling the end of some other 'Behavior'.>-->-- > signalB c = Receive (send c () >> yield)>signalB::(SplitChancx)=>c()->Behaviori>signalBc=Receive(sendc()>>yield)

>-- | A @Behavior@ that discard its first input, returning the passed Behavior>-- for processing subsequent inputs. Useful with 'Alternative' or 'Monoid'>-- compositions when one wants to ignore the leftover 'yield'ed message.>-->-- > constB = Receive . return>constB::Behaviori->Behaviori>constB=Receive.return