[Haskell-cafe] FRP question
pedagand at gmail.com
Sun Aug 17 19:38:32 EDT 2008
> I'm interested in FRP, have read several of the papers and am wondering
> if it could be applied to writing multi-client server programs.
That's funny: in the last few months, I have developed a
functional-reactive framework for large scale distributed system
programming. You can find the source code and a technical report here:
This code is in OCaml but the concepts can be translated in Haskell:
advised by Conal Elliott, I have already written the core of Opis in
Haskell (i.e the Arrow instances and a small network simulator) to
ensure the feasibility of a purely functional implementation. The
implementation in Haskell is based on the Mealy automaton while my
code in OCaml efficiently emulates this construct (based on
suggestions of Zheng Li, Oleg Kiselyov and Jacques Garrigue).
> What would be the input type events for such a system? What would
> be the output type events? How would the system handle the fact
> that it has to multiplex several IO streams (sockets)?
In my system, the input events are network events -- such as a
received TCP message or a UDP packet as well as notifications
(connection closed, listening on port X, ...) -- or timer events --
such as "a timer has just fired", "the timer is correctly set up" or
"the timer has been removed" -- or user events -- whatever the user
wants to signal.
The outputs are commands to the "launcher" system: the launcher will
collect these outputs and interpret them in term of (side-effecting)
actions. For example, the reactive function might ask to "send the
data D to peer x": thus, the launcher will connect to x, marshal the
data and send it to x. Similarly, you can ask to listen on a network
port, set up a timer, send an event to the user, ...
The multiplexing is done out of the reactive function, in the launcher
system. For networking, for instance, it opens one thread per open
connection. Once a thread has retrieved a complete message, it sends
it to reactive processing by a "Chan" (in Control.Concurrent).
I hope the technical report is clearer than this rough description. I
can send you a more "haskeller-friendly" paper if you are interested.
> Should input events include new connection requests and shutdowns?
New connection requests are silent whereas a connection shutdown
raises an input event.
> Individual bytes? Streams of bytes? or higher level PDUs?
> What kind of output should be generated? Full PDUs? streams of
> bytes? Pairs of (connection identifier,data)?
I work at the message level. For instance, the reactive function
outputs "Send( destination_ip , TCP, data )", then the launcher
marshals "data" and sends it to "destination_ip". On the other side,
the launcher marshals the received buffer of bytes to the same type
and transmits "TCP_in( source_ip , data )" to the reactive function.
Hence, for the reactive function, values are typed "end-to-end", hence
reducing the risk of error in marshaling.
> How would such a system effectively hide the multiplexed IO going on?
Personally, I chose to hide this multiplexing on the "launcher" side,
ie. out of the reactive function.
As the "launcher" side is developed once and for all (by me), a Opis'
user will not have to deal with multiplexing: she just has to care
with processing well-defined inputs by reacting with the correct
> Is this sort of problem poorly suited for FRP?
According to my experience, developing peer-to-peer systems in Opis
has been a great pleasure, because of its simplicity.
On the other hand, my architecture is based on the Arrow type to build
the reactive functions. Hence, I work hand-in-hand with the
type-checker. When developing a protocol in Opis, it is sometimes like
working with a theorem prover: if you forget that a given event could
occur, the type-checker complains, for example. Hence, in the P2P
field, my tool is a complete alien: people say that it looks great but
don't want to invest time to learn it... :-(
The "side-effects" of using purely functional structures are plentiful
(and well-known here): ease of debugging of pure functions, modularity
(given a reactive function, I can run it live on a network, simulate,
debug, or model-check it without modification), ease of backtracking
(useful for the debugger and the model-checker), reproducibility (see
the complexity profiler), provability (see the use of Isabelle's
certified code), and so on ...
Currently, I'm developing a complete formalisation of the Mealy arrow
instance in Coq and, hopefully, one day, I will be able to develop a
complete P2P protocol in Coq ;-)
Hope this inspires you,
More information about the Haskell-Cafe