Skip to content

Instantly share code, notes, and snippets.

@i-e-b
Last active March 22, 2019 15:54
Show Gist options
  • Save i-e-b/7014423 to your computer and use it in GitHub Desktop.
Save i-e-b/7014423 to your computer and use it in GitHub Desktop.
Fusing FRP and the actor model

Fusing FRP and the actor model for expressive concurrent design

Points:

  • Syntax as Elm
  • Should use simple Signals, with no re-plumbing -- to allow live switching. Event like lifting model ala Elm
  • Live code swaps happen two ways:
    • no signal/effect type changes, only pure and signal code changed: like Live code in Elm.
    • type changes: all effects and signals must provide an upgrade path (like std server in OTP)
  • Supervisor trees should be built-in, not library.
  • Likewise, OTP state machines and servers should be composed of effect, (? pipe,) signal.
  • Actors can read and send messages, 'death' is another message, but typed. Spawner or supervisor can listen on these messages and pattern match on them (replacing exceptions)
    • At the language level, death and regular messages are records. Send vs. Receive are type-checked.
  • Monadic sequencing, stateful calls are message receiver aliases made available by exposed 'IO' effects (like http://lambda-the-ultimate.org/node/4786)
  • Binding between 'Effects' and 'Signals' through a data-flow system like pipes (https://github.com/Gabriel439/Haskell-Pipes-Library). No ability to mix pure and effects.
    • functions of (f : a -> Signal b) or (f : Signal c) are like Producer in pipes.
    • functions of (f : Signal a -> Signal b) are like Pipe in pipes.
    • functions of (f : Signal a -> Effect [...] ()) are like Consumer in pipes. This is most useful where the effect is Process.
  • Record syntax like Elm, but with support for type Rec a = {a | ...}; f : Rec a -> Int -> Rec a ...

Packages and dependency management

  • Specific compile-to-library / intermediary language.
  • Dependency from type and name inside package, rather than from external version.

Reading

http://hackage.haskell.org/package/pipes-4.0.0/docs/Pipes-Tutorial.html

Sketches

File IO Monad:

readFileTest : String -> Effect [FileIO] String -- the Effect kind takes an array of available effect sets, and a return type
readFileTest fileName = readText fileName

Exception-like handling:

supervise : Int -> Effect [Process, IO] () -- Process gives 'spawn', IO givens 'puts'
supervise n = 
    map (myActor) [1..n] >>= spawn >>= respawn
    with
        respawn {fail:String} = puts "The processed died, saying "++fail
        respawn {id:Int} = do
            puts "Respawning process "++id
            spawn (myActor id)

myActor : Int -> Effect [Process] ()  -- Process gives 'receive' and 'die' (in addition to the 'spawn' used above)
myActor n =
    let msg [] = die {fail = "empty message"}
        msg "die" = die {id = n}  -- die to be respawned
        msg _ = () -- dummy
    in  receive msg
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment