Why not program in Standard ML?

By: on October 8, 2014

I decided to learn a language from the ML family recently, because we are seeing quite a few good candidates whose strongest language is F# or OCAML. So I decided to learn Standard ML. Yes, I know, that makes no sense. But wait…

Standard ML is really small and easily learned. If you know another functional language, and know what polymorphism is you will be ready to start tackling a real problem in a few hours. It has a great module system, with abstract types and functors, if you switch off your OO sensibilities.

You can write in a single language, and compile to the CLR, JVM, Javascript, C, or assembly. Is there any other language that can say that? There are several compilers which have made major releases in the last couple of years.

I’m interested in MLton, because it compiles to C, and that makes cross compiling easy. It easily calls into, and can be called from C. Did I mention that there’s a standard way to do that in ML, called NLFFI (No-Longer Foreign Function Interface), which bolts on C’s type system to the SML type system for a high degree of compiler checking and total convenience. So it’s interoperability with C is not unique to MLTon – it applies equally to SML-NJ, and more than that: code that binds to C is portable between compilers.

Standard ML supports imperative programming through references and arrays.

That’s the end of the features…

SML has no dynamic dispatch at all. I think I would need to write quite a lot of ML to decide if this is a problem – the ecosystem seems to get by without it. If two modules don’t agree on a an abstract type, the data might have to be converted by copying. I’m yet to stumble on a library of abstract collection types and implementations, so it’s pretty much impossible for Standard ML developers to form the habit of using abstract types. In many scenarios I think you would find yourself implementing collections a lot, and writing a lot of glue code. That doesn’t sound all that powerful, does it?

There’s no native Unicode support, and no one has talked about it since 2005 as far as I can tell. There is an XML parser which supports Unicode, using it’s own abstraction for Unicode strings. The one JSON parser doesn’t support Unicode. A library for Unicode ought to prove adequate, if it was widely used, but the Standard ML libraries I have found are all islands.

In conclusion, I was briefly excited by Standard ML, and might still find a use for it. The limitations of the standard library mean it’s not well placed to catch the current swell of sentiment for functional programming. It’s probably still worth learning, just because it’s so easy. I’ll probably move on to F#.

I jokingly ‘commissioned’ the cartoon for this post to the office at large, and Tim obliged, much to my astonishment.



  1. Robin says:

    A “JSON parser” which doesn’t support Unicode, isn’t a JSON parser. JSON strings are Unicode strings.

  2. Morten Jensen says:

    How are things looking now?

    This project seems to deliver a Unicode-aware JSON parser in SML: https://github.com/igstan/sml-json

  3. pyon says:

    I have a library of abstract data types of collections: https://github.com/eduardoleon/typhoon . It is mostly based on Okasaki’s book on purely functional data structures, but I have several important improvements:

    * All the functions in my library are total, in the sense that they always return a valid result. Under no circumstance is an exception raised. You can grep “raise” to see it does not appear anywhere in the code. Similarly, all uses of pattern matching are exhaustive, so the Match exception is never implicitly raise either.

    * All the code is tail-recursive. This means that the call stack is never used as an implicit unbounded data structure. This makes both the time and space requirements of the algorithms explicit, so they are easier to analyze. (In fact, my original motivation was to analyze the cost of pervasive laziness.)

    * The signatures have been designed so that, by convention, they give you information about the complexity of operations. For example, in most cases, if a collection type provides an operation “val uncons : coll -> (elem * coll) option”, then extracting the head and the tail of that collection has the same asymptotic time complexity. Whereas, if the collection type provides two operations “val head : coll -> elem” and “val tail : coll -> coll option”, then extracting the head runs in O(1) time, but extracting the tail might take longer.

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>