Code Monkey home page Code Monkey logo

drama's People

Contributors

evanrelf avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

Forkers

nicolast

drama's Issues

Should `receive` evaluate (to WHNF or NF) the result of the callback?

Currently, the result of the callback passed to receive is written into an MVar as-is, for further consumption by another actor/thread.

If this value is not forced to WHNF or NF, this means the thread which performed the call may spend time/work to evaluate the value, which is counter-intuitive. Furthermore, if an (impure) exception is thrown during said evaluation, this would show up in the receiver, not in the actor that was called (let's not even consider what happens if the callback uses some withFoo internally and the resulting value depends on said Foo to still be "open").

Long story short, would it make sense to have a version of receive (maybe even receive itself) which evaluates the result of the callback (IMHO to NF by default) before "returning" it to the called?

`Eq` instance for `Address`?

Unagi's InChan has an Eq instance, so I imagine Address could get (a derived) one as well. This would help keeping Addresses in some list (and removing one of them later).

Instances for `exceptions` classes

Since the Actor monad is basically a ReaderT, do you think it'd be possible to add instances for exception's MonadThrow, MonadCatch and MonadMask? Of course, exception handling ought to be handled a bit different in an actor-style architecture, but being able to use bracket (and similar) to manage resources is quite important nonetheless.

As an example, currently I don't believe it's possible to write an actor which uses network-simple's listen and accept, to then cast any new client socket to some manager actor.

Alternative `receive`?

Currently, receive's type is (forall res. msg res -> Actor msg res) -> Actor msg (). As a result, when using it, a handler for all kinds of messages is passed in, used to process a single message (returning a result of a call call if needed), and, well, return ().

As a result, it's not possible to 'return' values out of a handler into the actor code calling receive. Hence, a "state" actor, as is provided as an example in the documentation, requires an IORef (or similar) which gets updated from inside the message handler.

This is, however, quite unlike how this would be done in Erlang, and (IMHO) how it should be done in Haskell. Instead of using an IORef and some forever $ receive _, one could use explicit recursion, passing through the state as a pure value.

Hence, I was wondering, could there be a receive' :: (forall res. msg res -> Actor msg (res, a)) -> Actor msg a, which would allow to implement a "state" actor somewhat like (writing this from memory, please forgive any type/syntax errors):

data StateMessage s a where
  Get :: StateMessage s s
  Set :: s -> StateMessage s ()

stateKeeper :: s -> Actor (StateMessage s) void
stateKeeper = loop
  where
    loop s0 = do
      s' <- receive $ \case
        Get -> (s0, s0)
        Set s -> ((), s)
      loop s'

Ideas and inspiration

Todo

  • Document concurrency / supervision / process tree semantics
    • When a parent actor dies, it's children get killed
    • When a child actor dies, it throws to the parent
    • These aren't necessarily the semantics I want

Exceptions thoughts

  • Actors should only have one way of communicating: via messages
  • Exceptions are another way actors get to communicate in drama, but that violates the actor model
  • Child death should be a message
  • Parent suicide upon child death should be handled by a higher-level supervision-style wrapper around the base actor, and should be triggered by message
  • Synchronous exceptions should never escape the current actor/thread, except via a message
  • Asynchronous exceptions should be treated as unrecoverable panics, and can override the previous rule by default

Ideas

  • Use bounded channels from unagi-chan
  • Re-implement in terms of async function from unliftio, and hope adding brackets makes it just as safe? Would allow MonadUnliftIO stuff.
  • Supervisor stuff?
  • Add isAlive and kill/stop functions (finally write to some MVar or something to indicate death? Or takeMVar to pull the rug out from under a process?)

Inspiration

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.