As someone reasonably versed in OCaml but knows nothing about SML, what are primary differences? Given that OCaml has much better tooling and more of a community, what draws people to SML still?
SML records are structurally typed and may be anonymous which makes a lot of things easier to write. I've heard Ocaml has been attempting to tack that on, but that leads to the next point of Ocaml syntax being a complete mess. Ocaml needs keyword arguments, but in SML, structural typing gives named arguments without all the extra syntax.
I find the `ref` syntax of SML much nicer to use than the mutable record syntax in Ocaml.
SML doesn't have all the dotted math operators for floats.
SML strings are immutable which lends itself to a lot of potential optimizations (and there's always byte arrays if you actually need to mutate).
Ocaml let vs let expressions are annoying to me.
SML has a standard. "The implementation is the spec" in my observation always leads to problems.
My wishlist for SML:
FIX USE COMPATIBILITY. It's intentionally not specified by the standard. This makes portable code very hard. I'd love to see an approach more like JS, but without dynamic imports (useless) and with support for something like GO_PATH plus maybe the ability to recognize and import from URLs (especially .git and .sml).
JS style template strings with interpolation (the type system is at least smart enough to convert primitives to strings) and multi-line capabilities. This would also be an easy backward-compatible way to add support for unicode. Guarantee the ability to implement them as UTF-32 with the knowledge that an advanced compiler could choose to internally represent them as UTF-16 or even Latin1 to save space (JS implementations have optimized to convert their ropes from UCS-2 to latin1 when possible with huge memory savings as even Chinese sites are 90+% ASCII).
Module Typeclasses should keep typeclasses from happening everywhere (looking at you Haskell) while still allowing them to be used for more than equality.
Unofficial first-class functor support needs to be made official.
Pick one of the 4-5 slightly different concurrency models and standardize it.
Things I want that are in SuccessorML:
Guards, "OR" shorthand, optional leading pipe in matches
> I find the `ref` syntax of SML much nicer to use than the mutable record syntax in Ocaml.
Maybe I'm missing something in SML, but OCaml has `ref` as well and it works just like SML's?
let x = ref 0
x := 12
print_int !x
> SML strings are immutable which lends itself to a lot of potential optimizations (and there's always byte arrays if you actually need to mutate).
OCaml's strings are also immutable. They have been immutable by default since 2017 and prior to that one could opt into this behavior via a compiler flag.
You are correct that Ocaml has a ref type (though I believe it is actually a special case of a mutable record with one field). Most stuff I've run into uses mutable records more than refs (granted, I'm hardly deep into the Ocaml way of doing things). There is a small difference between an immutable record of which one property is a reference to changing data and a mutable record where the record itself changes. I prefer the first though I realize this is mostly preference.
2017 was just 3 years ago. Loads of Ocaml stuff rely on versions much, much older than that. In any case, the idea of outright changing a formerly mutable structure to an immutable one would be unthinkable in most languages due to all the breakages it is likely to cause.
> You are correct that Ocaml has a ref type (though I believe it is actually a special case of a mutable record with one field).
> There is a small difference between an immutable record of which one property is a reference to changing data and a mutable record where the record itself changes. I prefer the first though I realize this is mostly preference.
In OCaml ref is defined as
type nonrec 'a ref = 'a ref = { mutable contents : 'a }
so it is an immutable record which contains one item which is mutable.
> In any case, the idea of outright changing a formerly mutable structure to an immutable one would be unthinkable in most languages due to all the breakages it is likely to cause.
I agree with you. I started using OCaml in 2018 but I believe many linux distributions stayed on OCaml 4.05 (the release before safe-string was default) for a while because of breakages.
> Module Typeclasses should keep typeclasses from happening everywhere (looking at you Haskell) while still allowing them to be used for more than equality.
I was under impression that Haskell's typeclasses plus a couple of most common extensions minus the namespace pollution are pretty much equivalent to ML modules+functors, so could you elaborate how exactly that should work?
Yes and no. They can do the same thing, but with varying amounts of effort. SML has what is essentially a hard coded typeclass for equality with special syntax for it as well (two single quotes instead of one). There can also be issues creating and overloading operators. There's still ongoing discussion about modular typeclasses for SuccessorML
Yeah... not only the fact that SML modules always left an impression of arbitrariness (SML97 and OCaml have some subtle semantic differences and neither of those choices seem to be inherently wrong), but also the sheer complexity of their theory compared to Hindley-Milner... seems that there just has to be a better way.
Ocaml's optimization is very good, but not perfect. For example, if you need 32-bit integers instead of 31-bit integers, your performance is going to tank due to boxing.
MLton is a whole program optimizer (rather than function at a time like Ocaml) and wrings out a ton of performance though compile times are quite a bit longer.
As of 3 years ago it wasn't, but maybe that has changed.
Whole program compilation isn't without its downsides though. It seems pretty common to develop in SML/nj because of fast compiling then doing final performance profiling and deploying with mlton (having a standard helps). Function at a time is also more amenable to caching and reusing part of the previous compile.
SML is standardized which is useful if you want to build an implementation for academic purpose. I don't think anyone seriously uses it outside academia however.
I have worked professionally with Standard ML for a few years, but my friends and I used to joke that I was probably the only professional Standard ML developer in existence.
A portfolio management website (frontend and backend) and a portfolio performance calculation engine. You're welcome to contact me on my personal email, if you want to hear more.