Skip to content

Commit

Permalink
new Mailbox/Messages pair as sender/recver
Browse files Browse the repository at this point in the history
  • Loading branch information
jberryman committed Jul 20, 2012
1 parent 02c9710 commit 5de59fd
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 16 deletions.
38 changes: 23 additions & 15 deletions Control/Concurrent/Actors.lhs
Expand Up @@ -181,6 +181,7 @@ This module exports a simple, idiomatic implementation of the Actor Model.
> import Control.Monad.IO.Class
> import Control.Concurrent(forkIO)
> import Data.Monoid
> import Control.Arrow((***))
>
> -- from the contravariant package
> import Data.Functor.Contravariant
Expand Down Expand Up @@ -242,14 +243,11 @@ TODO
:: Mailbox ((), a) -> Mailbox a

PLAN W/R/T ABOVE AND CHAN SPLIT
chan-split:
- no longer depend on contravariant
- copy portions of split-chan lib (see notes)
- do some tests, e.g. GC properties

simple-actors:
- newtype MailBox a = MailBox { send :: a -> IO () }
- newtype Messages a = Messages { receive :: IO a }
- change all inChan/outChan instances
- don't export constructors
- define instances (see Op, Predicate, other defined types):
- contravariant
Expand Down Expand Up @@ -326,33 +324,43 @@ Later:
CHAN TYPES
==========

By defining our Mailbox as the bare "send" operation we get a very convenient
way of defining contravariant instance, without all the overhead we had before,
while ALSO now supporting some great natural transformations on Mailboxes &
Messages.

We use this newtype to get 'Contravariant' for free, possibly revealing other
insights:

> type Sender a = Op (IO ()) a
>
> mkMailbox :: InChan a -> Mailbox a
> mkMailbox = Mailbox . Op . writeChan
>
> mkMessages :: OutChan a -> Messages a
> mkMessages = Messages . readChan
>
> -- | One can 'send' a messages to a @Mailbox@ where it will be processed
> -- according to an actor\'s defined 'Behavior'
> newtype Mailbox a = Mailbox { inChan :: InChan a }
> newtype Mailbox a = Mailbox { sender :: Sender a }
> 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:

> newtype Messages a = Messages { outChan :: OutChan a }
> newtype Messages a = Messages { readMsg :: IO a }
> deriving (Functor)
>
> -- Not sure how to derive this or if possible:
> instance SplitChan Mailbox Messages where
> readChan = readChan . outChan
> writeChan = writeChan . inChan
> writeList2Chan = writeList2Chan . inChan
> readChan = readMsg
> writeChan = getOp . sender
>
> instance NewSplitChan Mailbox Messages where
> newSplitChan = fmap (\(i,o)-> (Mailbox i, Messages o)) newSplitChan

> newSplitChan = (mkMailbox *** mkMessages) `fmap` newSplitChan

There isn't really a good abstraction for these AFAICS:

> divideMb :: Mailbox (a,b) -> (Mailbox a, Mailbox b)
> addMb :: Mailbox a -> Mailbox b -> Mailbox (Either a b) --MORE DIFFICULT!



Expand Down
2 changes: 1 addition & 1 deletion simple-actors.cabal
Expand Up @@ -66,7 +66,7 @@ Library

-- Packages needed in order to build this package.
Build-depends: base >= 4.3 && < 5
, chan-split
, chan-split >= 0.4.0
, mtl >= 2
, transformers >= 0.3
, contravariant
Expand Down

0 comments on commit 5de59fd

Please sign in to comment.