I've always felt that ML hit the sweet spot between functional and imperative programming. It affords conveniences such as algebraic data types and first-class functions, but unlike Haskell, it doesn't require monadic programming to use IO or mutable references.<p>ML also has an interesting module system, which achieves similar goals as object-oriented programming, but in a very different way. While mainstream "class-based" OOP identifies the data type with the unit of encapsulation, ML has "modules," which are separate entities from types, and which may both define types and values as members. However, a downside of this approach is that you sacrifice late binding, as the module language and "core" language are stratified into different layers. Instead, dependency injection is achieved through module-level functions, called functors,<p>A lesser-known fact is that ML originated as the scripting language for the LCF proof assistant (which is where the name "ML," or meta language, comes from). In the LCF tradition, the inferences rules of the logic are implemented in a trusted kernel, then clients use those inference rules to write tactic scripts that construct theorem objects. This design was supported by ML's module system: theorems were defined as an abstract type in a "kernel" module, and the inference rules were defined as functions inside the module. Here is a tutorial that explains the LCF design better than I can: <a href="https://www.cs.cmu.edu/~fp/courses/15317-f17/recitations/recitation7.pdf" rel="nofollow">https://www.cs.cmu.edu/~fp/courses/15317-f17/recitations/rec...</a>
> <i>a downside of this approach is that you sacrifice late binding, as the module language and "core" language are stratified into different layers</i><p><a href="https://people.mpi-sws.org/~rossberg/1ml/1ml-extended.pdf" rel="nofollow">https://people.mpi-sws.org/~rossberg/1ml/1ml-extended.pdf</a><p><a href="https://github.com/rossberg/1ml" rel="nofollow">https://github.com/rossberg/1ml</a>
and you get concurrentML. People get all wet in the pants by the actor model and CSP, but my god CML is much nicer in every way.<p>I had a weird introduction to programming. I spent my first half year doing php, and them went all in on scheme and sml. Which is nice in many ways, but I do have a hard time accepting many of the completely braindead (subjective opinion, of course) choices of most of the popular languages.<p>I do think clojure is a pretty nice compromise. Rich has good taste, obviously. Clojure's core.async could be less async and more CML in my taste. Wrapping a simpler async api in cml is easy. Implementing CML on top on core.async is either very hard or full of compromises.
[flagged]