Just checked the code examples in a current Standard ML compiler, and they work without modification and behave as described. That's why you should choose Standard ML for your next project.
Great example though. When looking at Idris I had the impression there was a logical end point of having the type system so descriptive that, given the type of a function, there was only one possible implementation.
I was introduced to SML via Dan Grossman's Programming Languages course [0] and it's quickly become my favorite programming language to work through problems and brain-teasers.
Shame there isn't more non-academic support for it.
That is such a good course. I really enjoyed it and need to go back and finish the third part with Ruby.
If you like SML, check out F#. I did part one of that course in SML, F#, Typed Racket, and Scala. F# was by far the cleanest and most concise for each homework assignment. (Most code was written in SML first and then ported to the other languages.)
About twenty years ago I endeavored to learn both Standard ML and OCaml, and I found I preferred SML. I'm not clear how OCaml has gotten more mindshare, but I really liked SML/NJ.
I suppose back then we were still in the throes of "object-oriented is best" and the "object" in OCaml had some pull
The phenomenon described in this article is actually an instance of Reynold's parametricity. This one of the free stuff you get for using a (reasonable version of) static typing.
This is a good argument for having argument types declared for functions and structures, but inferring as much else as possible.
The trouble with inferring everything is someone reading the functions has no idea what the restrictions are. The classic Python example involves "lists" (built-in arrays) vs NumPy arrays. They implement most of the same operators and functions, but with different semantics. For built-in arrays, "+" means concatenate.
From a language standpoint, there are only a handful of features I would really like.
* something like JS backtick interpolation. Strings are hugely important in day-to-day coding for a lot of domains. Baked-in utf8 and Rune (utf32) would also be nice to have.
* Leading pipe in cases and `| foo | bar => expr` (maybe guards too, but they can be subject to abuse)
* Module Typeclasses which make it harder to create typeclasses everywhere like Haskell, but also does away with some ambiguities and the special case `eqtype` typeclass. SML has a way to add operators, but without typeclasses, it's pretty useless and unsafe. While we're improving modules, bake higher-order functors into them (they are already widely supported)
* Bake Concurrent ML into the official spec
As you can see, not too many things. In fact, about half of them (or more) are already supported in some SML implementations.
Honestly, all the "new" syntax/features in languages like Java, Swift, or C# just seem like attempts to kluge them one step closer to SML.
At least three active SML implementations are working on implementing the fairly recent Successor ML spec (HaMLet S, MLton, and SML/NJ), so while SML has been around for a while, it's also an active language that's still moving forward. (HaMLet S is more of an experimentation platform than a production implementation, but MLton and SML/NJ are solid industrial implementations.)
I guess SML would be it then. I'm sick and tired of the OCaML community that tells you to use OCaML, as if it's better than SML, but then tells you not to worry about the OO parts.
F# is the best modern ML in my opinion. It has OOP, but the style is to only use it when you need to or for interoperability with .NET. Even the OOP stuff is done in a concise way. I think it's useful to have. For example, one can have immutable records with member functions, and that's useful for doing operator overloading.
Great example though. When looking at Idris I had the impression there was a logical end point of having the type system so descriptive that, given the type of a function, there was only one possible implementation.