[MLton-user] Sockets+Monads in SML?
Vesa Karvonen
vesa.a.j.k at gmail.com
Thu Feb 14 16:33:52 PST 2008
On Thu, Feb 14, 2008 at 9:14 PM, Wesley W. Terpstra <wesley at terpstra.ca> wrote:
[...]
> Haskell has the concept of Monads, which comes quite close to what I
> need:
[...]
> 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?
Note that you only need a fn -expression when you want to bind a
value. In particular, using monads, you can define the usual
sequencing operator
fun aM >> bM = aM >>= const bM
and your example would become (with all the required parentheses and
the last redundant bind removed):
fun f x =
myprint "hello\n" >>
read >>= (fn x =>
read >>= (fn y =>
myprint (x ^ y ^ "\n")))
> It would also be very helpful if pattern matching were available, eg:
>
> read (socket, Time.fromSeconds 10) >>=
> fn TIMEOUT => ...
> | DATA x => ...
As you know, you only need to add the parentheses to make the above
pattern valid SML.
> 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.
Do you have a specific reason to avoid threads? With threads you
could avoid using monads and just write the program in direct style.
Your example would become:
fun f x s = let
val () = print "hello\n"
val x = read s
val y = read s
in
print (x ^ y ^ "\n")
end
> The function approach suffers due to the syntax of SML.
Yes, I agree that the required parenthesis are a bit of a nuisance. I
would personally consider changing the syntax of SML to allow fn
-expressions without parentheses in these contexts like in Haskell.
The monad based example would become:
fun f x =
myprint "hello\n" >>
read >>= fn x =>
read >>= fn y =>
myprint (x ^ y ^ "\n")
But, if you put this side-by-side with the version with parentheses,
the different isn't really that large. If you avoid long functions,
which is a good idea anyway, the extra parentheses aren't much more
than a bit of a nuisance, IMO.
I find the let -syntax fine for functional programming, but somewhat
verbose for imperative programming (note the "val () =" in the earlier
example). I would personally ditch the let -syntax and change the
syntax of SML's sequence expressions to allow bindings like at the top
level. This would make imperative programming more convenient. The
thread based version would become:
fun f x s =
(print "hello\n"
; val x = read s
; val y = read s
; print (x ^ y ^ "\n"))
(One of the semicolons above is redundant.) In addition, it would
also make it much more convenient to use modules locally. Consider
(open DSEL ; ...)
vs
let open DSEL in ... end
> Does someone have a tidy way of writing code like this?
If you can't stand the parentheses, I would recommend considering threads.
With some monads, like parsers, something like the "pick" notation
described on the http://mlton.org/StaticSum page might feel more
comfortable.
> 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?
I don't know enough about the specifics of MLton's closure conversion,
but I would personally be more worried if MLton wouldn't be doing
something like that to avoid space leaks.
-Vesa Karvonen
More information about the MLton-user
mailing list