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.
- functions of (
- Record syntax like Elm, but with support for
type Rec a = {a | ...}; f : Rec a -> Int -> Rec a ...
- Specific compile-to-library / intermediary language.
- Dependency from type and name inside package, rather than from external version.
http://hackage.haskell.org/package/pipes-4.0.0/docs/Pipes-Tutorial.html
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