Regarding your points:
1. Yeah editor support sucks. I normally edit in text mode with my own minimal keyword highlighting or ocaml-mode.
2. Poly/ML can definitely generate binaries! Most distros ship with `polyc` that will build the binary for you. But this is just a shell script around opening the REPL and calling some dump image function (like how you build a binary on SBCL). MLton and Poly/ML definitely allow you to build binaries. I don't know about SML/NJ.
3. For sure a pain. I use rlwrap [0] to work around this, which is ultimately simple enough!
4. Interesting! I personally find Haskell-style decorations so much more a pain since they're not inline. SML is very much like other major languages in the way it does inline types (TypeScript, Go, C#, etc.).
It doesn't seem to send the right message these days if the idea is that working programmers are building lambda calculus interpreters or theorem provers? Even interpreting a lisp would seem more practical.
I think Practical Common Lisp was more in the right track for content but today I'd focus more explicitly on language design or backend system design.
Andrew Appel's book does already fill the language design slot though nicely.
3. Thanks for the tip! That will save me a world of pain.
To these points, I'd say
1. I find Emacs sml-mode is just about up to it. I do have complaints - I wish it would pull back the indentation more in lines that continue an expression, it doesn't handle multiple "where" clauses elegantly, it misaligns anonymous function alternatives - but every time I consider trying to fix them I decide they don't quite upset me enough. It's a slight pity though because I strongly believe a language should be auto-indentable (life's too short to indent code yourself), and SML is, just not quite with the existing mode.
2. I like to use Poly/ML for automatic builds during development and MLton for "production" builds - both producing executables. There are still problems on Windows, which doesn't have a properly native MLton port - the existing one uses MinGW which is ok-ish but not what I would prefer. (MLton has a code generator that produces C, so the limitation is that the runtime hasn't been ported rather than with the compiler itself.)
3. Agree, "rlwrap poly"
4. I like inline type decorations, but I also like to omit them most of the time. I think you do get some feel for when it's a good idea to add them, to clarify things for the call site or check your own intuition about the deduced types. Module boundaries (with signatures) also form a natural firebreak for out-of-control type errors.
Do you have/use any dependencies? Like a http/2 (or tls capable) web server, a database client or a gui library? If you do, how does that work with two implementations - if not... What kind of programs do you write/problems are you solving?
I've used sml-mode in Emacs for years, and I've never had the problem you're describing. On the contrary, I find sml-mode to be quite adequate for my needs. Can you elaborate a bit on what's causing you problems?
Edit: Ah, I see what you're saying. After finishing a function definition and starting a new, the cursor is wildly indented, that's true. But if you just type `fun` and press tab, sml-mode automatically indents the definition correctly.
> 2. I've used Poly/ML and SML/NJ so far. Both of them are purely interactive, meaning I can't just compile a program into ELF and ship it somewhere else without the compiler. That makes it a no-go for me for real-world use.
I can recommend MoSML for interactive development. It can also produce compiled binaries. When I want to produce efficient compiled code, I usually use MLton.
> 3. The interactive modes of Poly/ML and SML/NJ don't support readline shortcuts. They are the most cumbersome REPLs I've ever used.
Use the REPL in emacs, it's excellent.
> 4. Inline type declarations (as opposed to Haskell-style type declarations on a separate line) are very noisy - they make reading the code harder. Omitting them (which is the rule in SML in practice) leads to hard-to-decipher compilation errors when you write a new piece of code and you made an error somewhere which confused the type-inference about your intentions. Suddenly forgetting about a word or a set of parentheses in one function results in errors in another perfectly-good function. It's the horror of C++ templates all over again.
I agree, this is a pain point. I usually leave type declarations in comments before the definitions, but that of course has obvious drawbacks.
1. Both Vim and Emacs are horribly annoying with their automatic indentation for SML. There is a lot of fighting against the editor in this department. In Emacs e.g. you have to delete whitespace all the time, because otherwise you'd have top-level function definitions shifted 80 characters to the right.
2. I've used Poly/ML and SML/NJ so far. Both of them are purely interactive, meaning I can't just compile a program into ELF and ship it somewhere else without the compiler. That makes it a no-go for me for real-world use.
3. The interactive modes of Poly/ML and SML/NJ don't support readline shortcuts. They are the most cumbersome REPLs I've ever used.
4. Inline type declarations (as opposed to Haskell-style type declarations on a separate line) are very noisy - they make reading the code harder. Omitting them (which is the rule in SML in practice) leads to hard-to-decipher compilation errors when you write a new piece of code and you made an error somewhere which confused the type-inference about your intentions. Suddenly forgetting about a word or a set of parentheses in one function results in errors in another perfectly-good function. It's the horror of C++ templates all over again.