Hacker News new | past | comments | ask | show | jobs | submit login
A Tour of Standard ML (saityi.github.io)
279 points by saityi 5 months ago | hide | past | favorite | 133 comments

I love Standard ML. As an undergrad, I wrote a compiler in it (through Zhong Shao's course at Yale), and it remains the most fun I've had using a programming language, let alone a functional programming language. The syntax is so simple yet it is extremely expressive. Hindley-Milner types are great, and the pattern matching is slick. SML also strikes a logical balance between purity and practicality.

Dan Grossman's "Programming Languages, Part A" (In Coursera) made me fall in love with SML. Highly recommended.

This course finally made me understand the WHY of FP. Comparing and Contrasting the major programming paradigms at a high level, but also actually writing code was a great combination. Before that I just thought it was only used for people doing math and finance (which wasn't even close to right, lol)

SML is kind of like the lisp of FP. It's just the minimal core of parametric polymorphism and hindley-milner type inference, so as a beginner you don't spend thought cycles language-specific features (that would make it more useful as a general purpose language) - you just learn and understand the core concepts and techniques (such as building intuition for how to replace different kinds of loops with recursion and pattern matching) that will apply to all FP/HM languages.

> SML is kind of like the lisp of FP.

Lisp is the Lisp of FP.

SML is more the SML of FP. Alternatively, SML can be viewed as the Lisp of statically-typed FP, in that, loosely, SML : Static FP :: Lisp : DynamicFP

"Functional programming" is a term with a few meanings.

Notably, the paper that (I believe) coined the term, "Can Programming be Liberated from the Von Neumann Style?" by John Backus, spent a fair amount of ink on specifically calling lisp out, and contrasting it from what he had in mind. IIRC, he felt that FP was preferable to the lisp model because lisp gives you too much power: Mutable variables, ways of composing functions that are potentially more error prone due to domain/range mismatch gotchas, stuff like that could all be impediments to ensuring the correctness of programs. I think that, to some extent, a sort of Haskellian fastidiousness about correctness is what he felt this proposed functional style of programming was all about.

Scheme is the lisp of FP. My understanding is that idiomatic lisp is quite imperative.

So is scheme quite often. It appears functional looking at idiomatic scheme code relying on tail-recursive programming for loops, it appears procedural/imperative if you look at all the mutation used in scheme code (fun fact: the Scheme standards R*RS do not speak of functions but of procedures). Higher-order functions aren't used all that much in many scheme code bases which is odd from the perspective of a Haskell dev.

Thanks for the info. My knowledge of the lisp family is quite limited outside of emacs lisp (which usually has a quite imperative feeling).

With my limited experience lisp is significantly not functional, or better is definitely an outlier in an unusual direction in the cluster of functional languages.

To me it feels much more like a symbolic computation oriented language.

But maybe it is because I associate too much fp with some kind of parametric typing

Also got to know SML in this course. It changed a lot the way I code and think, even in Java.

What I would like is a language as simple as SML in the JVM. Kotlin was the closest thing I found with good adoption.

>SML is kind of like the lisp of FP

Out of curiosity, what is lisp the lisp of? (It's not lambda calculus, for that is the lisp of lisp.)

> SML is kind of like the lisp of FP

You don't consider lisp the lisp of FP?

Most Lisps (and certainly Common Lisp) have enabled a functional style, but were never particularly "pure". You have to squint a little bit and gloss over some parts to call them functional programming languages.

Haskell is the poster child, but quite rich in syntax and concepts. So while I wouldn't really agree with grandparent, it's at least defensible to see Standard ML as a small core, a kernel of functional programming languages.

I think here it is important to note, that the definition of Functional Programming is kind of fluid and has changed considerably over the decades.

For a long time, there was no distinction between pure- and non-pure FP langauges and Lisp was certainly considered a FP lang. Yes, Lisps are typically not pure FP, but they are still FP (unless you define FP to mean pure FP, but that's kind of not in line with usage of the terms).

That being said, much Lisp code (CL or Scheme alike) is probably as functional in style as Python code.

Seems like many around here got to know sml through this course. I hope Dan Grossman and his colleagues can see how much effect they had :)

Yes! I did this many years ago, when it was all one course. I only got around to doing the SML part but it really improved how I approached learning new programming languages and frameworks (not just FP languages). I'm very thankful for what I learned, it has really help my a huge amount in my career! I'd highly recommend it to anyone who feels overwhelmed with all the 'new stuff' coming out. Much of it can be learned much easier if you look a little deeper and can ask the right questions.

If you'd like to see more Standard ML, there's a small community on Reddit.


At https://saityi.github.io/sml-tour/tour/02-05-recursion.html the claim that "This is safe [...]; it will not explode the stack" is fishy. The function as written is not "syntactically" tail-recursive. A sufficiently heroic compiler could rewrite this example into a tail-recursive accumulator-based one, but is that really required by the specification and commonly implemented in ML compilers?

You are correct, and I will fix it. The goal here was to encourage recursion and assuage fears of recursion coming from other languages: if I remember correctly, Standard ML does define semantics around 'expansive expressions' which make them /safer/ than I think most imperative programmers (my targeted audience) would expect, but this particular example would throw an exception.

To fix it, I will rewrite this section to say that the standard requires optimising /tail-recursive/ calls away, and modify the example to be iteratively recursive, but I'd still like to assuage fears of recursion in the tour. The 'while' loop in SML is actually just a derived form, and is rewritten to recursion; there is no looping in the language. Do you have any suggestions for rewording?

This is a work in progress that I was looking for feedback on :) Thank you! If you see anything else fishy, please let me know.

Thanks for your answer! I don't have any specific wording suggestions. If you're willing to add a specific section on tail recursion, I think you might leave this example in place (with the first paragraph of the current text) and then show a tail-recursive version in the next step (with a slightly modified version of the second paragraph of the current text).

Ocaml seems to get more buzz, but about 20 years ago I tried my hand at both OCaml and SML/NJ and found that I actually far preferred the latter. SML is a very nice, consistent, and practical language.

Here's a pretty thorough comparison of the two http://adam.chlipala.net/mlcomp/

Ocaml decided to be on the "large" while sml kept small it seems. I loved that trait (through Dan Grossman's MOOC). To the point that I found it even nicer to interact with than lisp.

The smallness of SML is a big part of why this is 'A Tour of Standard ML' instead of 'A Tour of OCaml' or 'A Tour of Haskell'. It's small enough to learn in a couple days (in my mind!), but it has all of the niceties of statically typed, immutable functional languages, so it provides a good introduction to those ideas.

That said, I love how small it is, too. Every time I go back to SML, I find it refreshing how much power there is in a few simple ideas expressed well.

the benefits, how I see them, is that the language never impedes your mind.. there are like 5 ideas, and the rest is pure thinking.

but well I was acquainted to typed FP before, to some or the mere mortals (just kidding) it might look like a sad joke.

ML for the Working Programmer is also an excellent reference. It demonstrates the construction of a theorem prover. As a matter of fact, Isabelle was built with SML.

There's also a famously concise intro to SML (in 22 pages!) by Mads Tofte:


do you know uses of ml modules for network protocols or rendering systems (gui or else) ?

You might want to check out "Unix system programming with Standard ML" by Shipman. The first half of the book covers the basics of SML and the Posix & C interfaces, and also discusses building a simple TCP client and server. The second half of the book is a larger project building a web server:


Sadly I don't. I have only used SML for theorem proving and formal transformations from initial axioms to code.

yeah it would be cool to explore some different domains with ml, outside the usual logic/fp thing

Today's there's also F#, which is the "" to Ocaml's ";;" and to SML's ";".

Concurrent ML is definitely worth looking at.

ConcurrentML has a outgrown its name. It is available in many different languages. I recall hearing Mike Sperber saying that his company usually just re-implemened it in whatever language they happened to work in that week.

It is a really nice system that is similar to go, but the primitives it gives you are in a way a generalisation of go's concurrency primitives.

Can you point me in the direction of any reading on this, I’d be interested to hear about it.

I don't get the issue with ;; in ocaml, literally all it does is force evaluation in the repl. You will never write it in code.

Don't you also need it for top-level declarations in a file?

They can (almost?) always just be inferred, I think (it's been a couple of years since I programmed in ocaml daily).

I personally like using them anyway. If you've done something wrong I recall the parser can sometimes give better error messages if it has them around to orient itself. And for all the complaints people seem to have you really can grow to like them aesthetically - there's something pleasantly blocky and definitive about them I find, like the satisfying thock of a good keyboard.


The Concurrent ML library for F# is https://github.com/Hopac/Hopac

OCaml has come many, many, many miles from 20 years ago, and continues to make improvements year to year.

Sounds like multicore OCaml is finally nearing completion:


Great, although in the age of micro-services and threading exploits, being mostly mult-process isn't that bad.

What kind of stuff are you making with SML?

This is neat, and I didn't spot any mistakes in my first very light skim through.

One practical nit is that the position of the "forward" button moves around depending on how long the section title is, so you have to keep chasing it. Possibly it could move to the left of the section title, so back and forward buttons are clustered together in a fixed place?

Yep! I will get that fixed. Thank you for the feedback!

If you find anything else, issues and feedback are also welcome on the issue tracking @ https://github.com/Saityi/a-tour-of-standard-ml/issues -- I'm primarily a backend engineer, and this is my first foray into frontend; even nitpicks like this are very welcome. :)

Very clearly written, easy to consume, easy to navigate. Thank you for this!

Thank you for checking it out!

Does anyone know how fast MLton (whole-program optimization) programs run in comparison to other languages?

When I converted a CPU-intensive program from OCaml to MLton-compiled SML, without changing any of the algorithms, I got a 30% speedup. That was more than 10 years ago though, and both compilers have seen some improvement since.

OCaml now has flambda, which is a significant improvement on its baseline optimizer. I think the difference wouldn't be that wide today :)

Obviously depends on what you're doing, but in my experience it generally isn't as fast as the C++ I write and compile with a modern compiler. Maybe comparable with other optimised compiled languages with GC. It's not magically fast, but it is quite good at avoiding unexpected slow cases - which can help it "win" even against C++ sometimes.

I generally test with MLton and Poly/ML, and MLton does not always produce faster executables, though most of the time it does. Poly/ML is a good compiler as well, and it has much faster compile times.

I assume there is a lot of pointer indirection as is the norm in FP languages that hurts performance quite a bit

Yep, I guess it doesn't quite reflect the modern reality for memory and cache access there - although at least primitive types are unboxed, inlined in arrays and records, and represented as machine types. There are probably more opportunities to do that in a whole-program compiler, which doesn't need to carry type information between modules.

I believe it also doesn't do SIMD auto-vectorization, which is a recent improvement in C++ compilers that's made a difference to some of my own code.

It's about as fast as golang. It won't match the speed of a non-GC'd languages like C/C++/Rust (not that I'd expect any different).

Faster than C years ago, nowadays it may be different because of all the optimization work put into C compilers. Long compile times though.

The automatic currying of functions is awesome, even if the declaration syntax would take some time to get used to, although it's quite similar to the new JS anonymous fn declaration (x => x + 1), or maybe the inspiration is reversed.

I had the same problem getting used to Nim with it's Pascal inspired syntax. But being different is rarely a bad thing as long as it works.

> it's quite similar to the new JS anonymous fn declaration (x => x + 1), or maybe the inspiration is reversed.

Yup, that family of syntax descends from Standard ML.

SML is a great language, but the tooling around it wasn't so hot the last time I checked (admittedly more than a decade ago. With a medium sized ( a few ten thousand lines) project I had weird build errors and in the end wrote a makefile. Not fun).

To this day, I don't understand why Google made Go instead of working off of SML. While the go ecosystem is better due to the millions of man-hours poured into it, the language is inferior in every way.

To elaborate, CML is better than golang's channels and isn't broken (requiring mutexes over channels to avoid breaking qualifies as broken). SML syntax is simpler to learn, but still offers much more powerful abstractions with pattern matching. SML uses options instead of null pointer exceptions. Hindley-Milner types are clearly superior to Golang's type system (especially things like empty interface). SML has had generics for almost 25 years now while go languishes. SML has immutable data structures and they are the default for almost everything. Golang has implicit types, but SML's implicit types are much better -- especially structurally-typed records. SML's modules are amazing and simply have no comparison in go. Finally, SuccessorML is doing work toward adding a few new features to the language (for example, module type classes), but the language has an actual specification that anyone can implement (and many have) rather than the implementation effectively being the spec.

I think it's a bit misleading to say that "Google developed Go", as if it were some kind of strategic play. Go wasn't a top down product; it was created by the engineers who had the idea to create a new language, and hope to make it a popular one at Google. But even today, Go is not one of Google's top internal languages; Java and C++ apparently still dominate on the backend.

As for why Go isn't SML, just look at the original team. They had a background in languages like C (Ken Thompson , Oberon and Modula (Robert Griesemer) and Aleph, Newsqueak, and Limbo (Rob Pike). Nobody on the core Go team have ever been fans of functional languages or of complex type systems.

I look at go and I see an admission of defeat in programming language design. The central idea of go is that the way to have a language that is productive in the large is to impair it as much as possible. Unfortunately this idea seems to have been wildly successful.

Google hires the best engineers who somehow can't be trusted to use a modern programming language if Rob Pikes words are to be taken literally

Have you SEEN what happens when you give an extremely clever engineer some rope?

Haven't we got the languages swapped in this comparison? I'd argue SML gives you less footguns, since the typechecker is much more restrictive about what kind of code it will allow, whereas Go will allow you to write code that has a nil error, for example.

Recently, in the wake of a moment of lucidity, I decided it was time to nope out of using cats, or anything like it, in my Scala code.

It's like that one year that I got myself addicted to Minecraft.

This reminds me of a paper in the latestest edition of sigbovik [0], "Applications of Standard ML at Google" [1].

It could also use some newer things like better support for unicode strings.

[0]: http://sigbovik.org/2019/proceedings.pdf

[1]: Page 170, Also here: https://github.com/solb/sigbovik/blob/master/papers/SIGBOVIK...


Especially cruel is the "andalso" in the closing sentence.

I'd add that the SML dialect AliceML, influenced by Mozart/Oz, has incredibly nice lazy, concurrent, distributed, logic, etc. extensions. It's really sad it's abandonware:


ALiceML is indeed a rather nice set of extensions to SML. If you pull the code from here:


and make sure you have all the dependencies installed first, it does build on linux and its fun to play with.

I am currently working on a AliceML derived language and if there is any interest I'll post a note on HN - once its a bit futher down the line.

Please do post once it's ready!

Because Go traces its lineage to Limbo and Alef (among others). Rob Pike worked on Limbo, in particular, and was present when Alef was being developed. Those languages have some direct inspiration for the concurrency model in Go (along with CSP which they all trace to). It makes sense to continue down a path they'd already charted and believed in.

> (requiring mutexes over channels to avoid breaking qualifies as broken)

I've used Go channels plenty of times without any explicit mutexes, so I'm not sure what you're talking about here.


I'd add that these aren't just theoretical (EDIT: I forgot that his article linked to this paper).


Go doesn't actually implement CSP correctly. That would require some changes. This provides a high-level overview.


Threading is hard and gets a lot harder when you introduce pointers or mutable data. This is even harder when your type system is terrible. I suspect that Go trying to solve this would result in a language that looked a lot like Rust with a Garbage Collector.

You've gone from "Go channels are broken because they require mutexes to use" to "Go doesn't implement CSP correctly." The former is demonstrably not true and the latter is academic. (Although you did reference a good study on concurrency bugs in Go, but this seems unrelated to either of your claims.)

You aren't doing your argument any favors when you're so hyperbolic. Go channels are manifestly not "broken."

> I suspect that Go trying to solve this would result in a language that looked a lot like Rust with a Garbage Collector.

And yet you honestly can't understand why the designers of Go didn't go down that path? Rust is significantly more complex than Go and much harder to learn.

The latter being academic doesn't mean it is not also of practical import to correct usability.

Never said it doesn't. But no further explanation was offered.

Bottom line for me is that if you're going to be snotty about something, then at least be correct. Or better yet, don't be snotty in the first place.

Your elaboration could as well be described as a list of language features that SML has, and that Go's developers have publicly said are undesirable.

I know they simply cannot have several of them due to the language design choices. I know they are working on some like generics. Others like sounder typing, better type inference, and functioning concurrency primitives seem like sound goals for any language that already has those things.

Which of those features have they said the don't want?

PL theoretic superiority was not the design goal. Golang was intended to be a pragmatic, bread-and-butter language for large teams with churn. Bad code needs to be screamingly obvious. It also needs to be very easy to learn. FP langs can never fill this role because it's fundamentally more difficult to think in FP terms than imperative terms. Maybe for small internal projects. (But if it's successful, it'll get rewritten in Go/Java/C++; people simply can't handle FP.)

'A Tour of Go' inspired this. The format and some of the material come from there. I think it ended up shorter than the Go tour, and I was hoping it would be very easy to learn Standard ML from it, as I do consider it to be very easy to learn. You can pull up the CML examples next to the Go ones, and other than syntax, they should be the same:



There are differences, but once you get to that point in either tour, the differences shouldn't make it hard to read; if it is hard to read or understand, that would be welcome feedback, as I have failed in my attempt to present Standard ML well. :)

(I originally posted this as a 'Show HN', hoping for feedback, so it is totally welcome.)

It is very readable. Helped me get over my initial prejudice after I actually looked at it.

Thanks for checking it out! :)

> Bad code needs to be screamingly obvious.

I'm not sure I understand why this is true for Go rather than a statically typed FP language. If anything, I'd consider languages like Haskell or ML to be better at this.

- The obvious case is handling `nil`. In Haskell, you'd treat this as `Maybe a`, and it's obvious that you're not handling the nil case since the pattern match is incomplete. In Go, you get a nil pointer exception at runtime. You could check for the nil case for every pointer, but that's too onerous, so now you're left with relying on the programmer on checking

- Go doesn't have exceptions, which removes some of the hiding of bad code (see https://devblogs.microsoft.com/oldnewthing/20050114-00/?p=36...), but you can still accidentally use a result when an error is return (in fact, you have to return something!). In Haskell, you're forced to pattern match on an `Either`, which again exposes bad through an incomplete pattern match.

I don't think these are arguments for FP per se, but I do think that statically typed FP languages (and the languages they inspire) are much better about removing footguns and making bad code hard to write, simply because the typechecker is so restrictive. As a more general principle, instead of making bad code screamingly obvious, make it impossible to write!

Now, you mention later in the thread that you've already used Haskell before, so you're probably aware of all this and I may misinterpreted what you meant. Did you mean a different form of bad code?

FP is easier to reason about because humans have a hard time with implicit state. Just because you don't know it doesn't mean its hard. That's why functional-ish things like Redux are taking off, and every new language except Go has incorporated significant functional features.

> Just because you don't know it doesn't mean its hard

I spent a long time learning Haskell and have written enough Clojure especially to safely call myself an expert in it. I obsess over languages (not proud of that btw). FP is hard. It's too hard for most programmers. A lot of people avoid saying this but it's true. It's hard in a way that you can't fix with experience.

That's why the tooling for it sucks. Suppose you want to make an IDE or even an API for your product. Do you want a lot of people to use it? Then you use ${BLUB}. Heavily abstract stuff dies. Look at Tensorflow vs. Pytorch. Tensorflow 1.0 had this wonderful functional, declarative, immutable way of writing neural networks, but people protested because they couldn't mutate variables in a for loop and have it automagically autodifferentiate. Abstraction kills network effects.

> every new language except Go has incorporated significant functional features

None of them come close to the semantics of FP (except Scala, but its negative adoption rate kind of proves my point). They all allow side effects which breaks the first rule.

You can say they stole some of the convenient syntactic sugar from FP, like pattern matching and lambdas (e.g., Kotlin and Rust). Great. So what advantage do FP langs have now? Making it hard to do I/O? Category theory? Having unmaintained compilers?

Haskell was designed for theory. SML was designed to combine being pragmatic and easy to teach (not only the language, but how to implement). Other than syntax, SML's fundamental nature is much closer to Rust (with a GC and simpler syntax and without lifetimes, macros, or traits).

In any case, let's look at those haskell "hard parts" and contrast them.

Haskell treats everything as immutable. SML is NOT always immutable. It simply adds some (very sane) constraints on where mutation can occur which makes reasoning about mutation easier.

Haskell forbids side effects. This is an illusion of course (you'll find high-performance libraries often use the unsafe IO stuff). SML embraces side effects though general practice is to restrict them to specific modules to make the program easier to reason about (a good practice in pretty much all languages). You can definitely write imperative pieces of code if it improves performance.

Haskell is lazily evaluated. This can be a performance boon for some things, but is a bane to find and fixing performance bottlenecks. SML is eagerly evaluated like most other languages.

Haskell is crazy for typeclasses. They use them everywhere, but they often complicate actually using things. SML does not have type classes, but SucessorML (the next version) is looking at adding module typeclasses instead. These will have most of the same features, but because they are in the module instead, it should put a big limit on their abuse and make their use easier to track.

SML's big "ivory tower" ideas are: powerful type system, pattern matching, option types everywhere, first-class functions, and modules (essentially as a replacement for classes though that is not entirely true).

SML really is the whole package. The best parts of functional programming combined with the best parts of mainstream languages (restricted to the "good" subset) all tied up in a language definition that manages to reduce the amount of syntax compared to something like Java or Go while increasing the amount of power while at the same time not turning into an unreadable mess (it's pretty hard to write unreadable SML code).

I assumed Standard ML was more like Haskell than it is. Going through OP's tour, I notice that it has enough features to actually be usable. It has primitives for concurrency and OS APIs.

It's even easier to use if you go with Poly/ML's pthread support. CML is relatively more complex and less supported from what I can tell.

Because Rob Pike is a hack

Could you please stop posting unsubstantive comments to HN? Also, personal attacks are not ok here.


The go team had an explicit goal of very fast compilation - including low scaling with the number of files (avoiding the Nfiles^2 that C++ tends to have because of include files). It's not obvious to me that this is compatible with SML's module system and Hindley-Milner, although I'd love to be proved wrong.

OCaml compilation is just as fast as Go.

Great. SML compilation was noticeably slow last time I used it, but maybe that's changed.

Ocaml has way more paid development time than SML. MLton guys can't focus on everything, so they've decided final performance is more important than compile time. SML was designed with few ambiguities to the syntax (simpler for students to implement), so theoretical compile times could be very low indeed. If they had Google money behind them, compile times would definitely be better

The other thing is whole-program optimization vs method-at-a-time. A lot of SML devs use New Jersey for fast compiles when developing and MLton when deploying. You can get rid of a ton of stuff in functional languages once you do a whole program compile, but that will always take more time. MLton could really use a second, faster compiler, but I'm just appreciative of all their effort to make the current compiler output fast code.


The expansion of the acronym is more an etymology than the language's actual name. Calling it "Standard Meta-Language" would probably cause more confusion for most people. Similar to how nobody ever refers to Fortran as "Formula Translation", or APL as "A Programming Language", or COBOL as "Common Business-Oriented Language", or BASIC as "Beginner's All-Purpose Symbolic Instruction Language^H^H^H^H^H^H^H^HCode".

(edit: basic, not basil)

BASIC = Beginner's All-Purpose Symbolic Instruction Code (not Language).

Those abbreviations do not collide with a more common abbreviation in the same domain. Standard as a prefix in this title does not disambiguate its meaning. Anything to clarify it is a programming language would be nice.

The name "Standard ML", with a capital S, is not ambiguous - it's (still, just about) unambiguously the name of a programming language.

You have to call the language something. For decades it was mostly just referred to as ML. In recent years people (including me) have started calling it Standard ML explicitly to avoid confusing people who now expect ML to mean machine learning. It doesn't always work, as we see.

Expanding to "meta-language" sadly is no good either, since nobody has ever called it that and most practitioners wouldn't even recognise it.

SML is a possibility that's used often enough, but there's a semantic difficulty there - the difficulty is that Standard ML is the standard version of a language called ML; it isn't quite a language called SML.

> You have to call the language something. For decades it was mostly just referred to as ML. In recent years people (including me) have started calling it Standard ML explicitly to avoid confusing people who now expect ML to mean machine learning.

IIRC, both SML and Standard ML were used to distinguish it within the ML family of languages before machine learning became popular.

> For decades it was mostly just referred to as ML. In recent years people (including me) have started calling it Standard ML explicitly to avoid confusing people who now expect ML to mean machine learning.

Aren't they 2 separate languages? They have 2 separate Wiki articles:



Or maybe the difference is more like Lisp vs Common Lisp.


Well, what would you suggest?

"A Tour of Standard Meta-Language" is nonsense. If there's one really unfortunate thing about ML, it's that the expanded (original? source?) name of the language is so meaningless that nobody bothers to learn it. The name of the language really is ML, not something that ML happens to stand for. Though as others have said, the same is true of BASIC and COBOL.

"A Tour of SML" is still an abbreviation, is less clear for anyone who knows what Standard ML is, and is not the original title.

The first two hits that come up when I type ML into the algolia HN search (https://hn.algolia.com/?dateRange=all&page=0&prefix=false&qu...) are

"ML From Scratch, Part 1: Linear Regression" (301 points), which is about machine learning


"ML for the Working Programmer, 2nd Edition" (266 points), which is about ML

Which is the more ambiguous? Noting that the second one is about a thing whose name is ML, while the first is about a thing that is sometimes casually abbreviated to ML.

If you're worried about the collision, I'd suggest petitioning the machine learning people to stop using the acronym. ML the programming language had been around for decades before it was common to use ML to mean "machine learning."


The "Standard" in the phrase "Standard ML" is all the context that someone with a reasonably broad knowledge of programming language history (as is common among the HN crowd) would normally need.

For everyone else, hey, click a link, learn a thing. Clicking links and learning about new things is theoretically a primary reason to come to HN in the first place.

ML as a language name has a historical etymology, but its not really now any more of an abbreviation than KFC is, its just a name.

> Abbreviations without context are not suitable for HN titles

Write hn@ycombinator.com and get dang to make it a rule. Until he makes that rule, I call bullshit.

> use the original title, unless it is misleading


It is already part of the guidelines.

"misleading" and "potentially ambiguous" are not synonyms.

Standard ML is a well-known language. A title isn't misleading if it refers to that.

And nobody agrees with you.

> a more common abbreviation

Google "standard ml" returns 1,090,000,000 results. At least the first page refers only to the language.

Google "ml machine learning" returns 183,000,000 results.

Google "ml programming" returns a page with some links referring to the language Standard ML and others to the language ML, none to machine learning.

I didn't even know there were people referring to machine learning as ML.

Standard ML outdates the common usage of ML as "Machine Learning" by a few decades though.

I'd like to do the exact opposite. Many a times have I hoped for a good article about a good language, but got presented with a memefied statistics article.

At least on HN I still know what NLP stands for…

> At least on HN I still know what NLP stands for…

Neuro-Linguistic Programming?

I agree that the abbreviation ML is too ambiguous to be useful in a title without added context. This title is particularly misleading due to its lack of context.


> use the original title, unless it is misleading


We are agreeing that ML as an abbreviation on HN can be misleading.

Is there a "standard" for machine learning that's regularly capitalized?

Title case.

Title case is inherently misleading and, therefore, should not be used.

ML is a entire major language family that itself has roots in lisp. I've starred the "important" ones you'd probably know.

In the "core" ML family: original ML, Standard ML (SML), Concurrent ML (an extension of SML), Polly ML (yes, it's a different language that SML is implemented on top of).

Then there was the "lazy" family: Idris, Lazy ML, Miranda, Haskell, Purescript, and Elm (though it's not actually lazy).

Then you have the "pragmatic" family: Caml, Ocaml, Coq, F#, f-star, Alpaca, and Scala (these last two are somewhat less related here).

You also have the rough category of ML without a GC: ATS and Rust

There's a few others, but I'm not so familiar with them.

How are any of these coming from Lisp? I was under the impression that ML was a completely separate camp from Lisp.

ML was implemented in Stanford Lisp on a DEC10. The layout of the language is very lispy. Make parens around functions non-optional and add them around let, and a couple other constructs makes the code almost indistinguishable from lisp. First-class functions everywhere, linked lists, and garbage collection were also very-much tied to lisp at the time. Initially being implemented on top of Lisp is probably a key reason these were present.

Idris is eagerly evaluated.

You are correct (I'm sorry, I don't know much more than what I read in a cursory inspection some time ago). I should have called it the "lazy and/or completely immutable" category.

As are PureScript and Elm. Maybe "lazy" is just no longer a good name for the branch as a whole, given that it keeps growing new eager leaves.

As someone familiar with the name already, expanding it would be very confusing for me.

As someone familiar with Standard ML, you probably aren't the target audience of a tour of the language. The goal of this article is obviously to introduce new users to the language. Tricking users into clicking the link by being vague is not constructive way to recruit new users.

If anything, shortening to "SML".

Nobody says "Standard Meta Language", though.

I find it very irritating how people try to make others give up established words and phrases. There will always be ambiguity.

See also "crypto" or the recent spat here on HN about an old SQLite page.

I thought the M stood for module?

Nah, It's Meta (source: https://en.wikipedia.org/wiki/Standard_ML).

SideNote: I have a friend though, who used it for almost 15 years and thought the M stood for Math before we spook about this.


It’s not misleading for anyone with a bit of programming language culture, which is probably the majority of readers here.

Standard ML is very well known, even to people who have never programmed in it.

I think you're simply wrong. You simply know Machine Learning and are probably interested in that.

I bet you wouldn't argue that Machine Learning or Artificial Intelligence headlines need to be spelled out.

And what's the damage? There are very few Standard ML submissions here. You're being "misled" into reading a sentence or two that don't interest you like... once every year?

>Expanding "ML" to "Meta Language" would make this title clearer.

No, I don't think it would make it clearer, at all.

Is there any such thing as "standardized" machine learning at this point or even in the foreseeable future? The target is moving too fast.

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact