[MLton-user] Sockets+Monads in SML?

Wesley W. Terpstra wesley at terpstra.ca
Thu Feb 14 11:14:57 PST 2008


I am planning on implementing a fairly large network application in  
SML. It's a port of the work done in my thesis. Much of the original  
code consists of event handlers connected in sequence. I am looking  
for an SML idiom that can express this cleanly.

Haskell has the concept of Monads, which  comes quite close to what I  
need:
> infix 0 >>=
>
> fun f >>= g = f g
>
> fun myprint str ret = (print str; ret ())
> fun read ret = ret "result"
>
> fun f x =
>  myprint "hello\n" >>= fn () =>
>  read >>= fn x =>
>  read >>= fn y =>
>  myprint (x ^ y ^ "\n") >>= fn () =>
>  ()
The method 'read' would in reality return from the method, but install  
the 'ret' function to be called once the data was ready. The problem  
here is that 'fn' can't be used without ()s. Is there any way to  
introduce variables without excessive bracketing? It would also be  
very helpful if pattern matching were available, eg:

read (socket, Time.fromSeconds 10) >>=
fn TIMEOUT => ...
  | DATA x => ...

The problem I'm running up against is that only 'let' clauses and  
function declarations can introduce variable scope. AFAICT, the let  
clause prevents me from popping out of the method after installing a  
signal handler. The function approach suffers due to the syntax of SML.

Does someone have a tidy way of writing code like this?

Also, I am concerned by MLton's closure conversion. With this style of  
programming, there are a *lot* of bound variables which pile up  
towards the end of the event  chain. As I understand it, the closure  
of MLton is converted into a datatype which represents the function to  
call + it's free variables. The longer these chains of event handlers  
get, the more free variables in the later functions. My concern is  
that it will cost me a lot to convert these datatypes. I am under the  
impression MLton will flatten them out into one record at each step  
rather -> O(n^2) cost for n steps of function nesting (if nearly all n  
variables are used in the last step, which is quite typical). Should I  
be worried?

For comparison, when I program this in C++ I create a class with all  
the variables I will need and member methods which handle each step in  
the chain. I draw a nice flow chart for all the events and which leads  
to whatever, and then carefully manage the lifetime of the object and  
at the end of each step hook the 'next' member methods to the event  
loop. This is very error prone (missing the an alternative for the  
next step, missing cases where the object stays live, killing the  
object too soon, unhooking events that weren't hooked, etc). However,  
it also doesn't waste a lot of work rebuilding the record. I was  
hoping that a functional language like ML would relieve me of needing  
such an object (closures = garbage collected) and pattern matching  
could help to ensure branch coverage.




More information about the MLton-user mailing list