Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
The Future of Standard ML (2013) [pdf] (cmu.edu)
138 points by virtualwhys on July 14, 2016 | hide | past | favorite | 79 comments


Cutting to the chase: use Haskell or Scala or F# if you need to do some scripting or build a web application that requires lots of different tasks (being a web server, rendering templates, connecting to a database, etc.). Haskell and Scala have great libraries and polymorphism that allows you to express things succinctly. Dunno much about F# except .NET.

Use OCaml if you want easily native binaries, predictable performance and need very little in the way of well-documented, high-quality third-party libraries.

Use Standard ML if you want to learn OCaml/Haskell/F#/Scala. Why? Ultimately it comes down to usability. First off, operators (not named functions) are to programming languages as icon-only buttons are to web pages; they are completely unusable. The only reason Standard ML avoided the plague of the operators is because it's a simpler language that was used less. Second, since it's a simpler language, you get a much cleaner introduction to things like monads and modules. It makes it very simple to jump into more complex languages like Haskell or OCaml or Scala.

I work on Ponyo [0] because I want to allow people (myself) to program at a high-level in Standard ML. Furthermore, I want to promote quality and usability. Basically, every function's type is annotated and we avoid abusing operators. The current state is such that you can parse CLI args, parse/marshal JSON, serve web pages, make http requests, browse file trees, and many other ideas in the works. But the most important part about Ponyo is that it is a large, (hopefully) well-documented project that others can study to learn Standard ML (and Haskell and Scala and OCaml and F#) better.

Scala, Haskell, F#, OCaml have their place and do their jobs well. If you don't know their place or just want to get exposure to the history behind these modern languages, I recommend giving Standard ML a shot. You can get started by reading the /r/sml wiki [1] or joining #sml on Freenode.

[0] https://github.com/eatonphil/ponyo

[1] https://www.reddit.com/r/sml/wiki/index


Coming from Scala I'd like to see successor ML become a reality. Whether it's 1ML, Ponyo, Ur (without the /Web), or another ML derivative that's not OCaml (petty, but the crufty syntax makes Scala seem elegant in this regard) isn't all that important.

As it stands every year Rossberg publishes a paper on latest 1ML enhancements; Harper does the same wrt to PLT, and by proxy SML. Meanwhile, nothing's really happening AFAICT in terms of the ML torch really being taken up and carried forward (beyond OCaml and Haskell).

Perhaps a charitable donation from an SV unicorn founder or two, corporate backing of some form, or academic backing similar to EPFL for Scala could really get the ball rolling.

Moving forward we've got OCaml and upcoming modular implicits; Haskell and the new module system, Backpack; and Scala's transition to Dotty -- basically a lot to look forward to, but would love to see SML in the mix, such a beautiful language...


What about Facebook's Reason? It's an alternate syntax for OCaml that hooks into the existing OCaml compiler toolchain.

https://facebook.github.io/reason/

Looks like they've used it to build all kinds of stuff (including the Hack/PHP compiler).


I find it interesting that you list all of the ML derivatives except the popular one.


Maybe its not that popular but I would mention ATS programming language http://www.ats-lang.org


Don't be silly; nobody uses Windows.


Poly/ML?


No.

I mean, I know Tiobe isn't great, but the only ML-derivative I see on the top 50 is F#. ML and OCaml crack the top 100.


F# is an OCaml derivative. I'd reckon that OP's feelings about F# would be rather similar to their feelings about OCaml.


The only objection to OCaml is "the crufty syntax," which I think F# has taken steps to improve upon.


But F# didn't bring along the beautiful module system from the MLs, nor does it have type classes. Polymorphism there is basically just the OO + generics variety found in C#. That can rub some people (like me) the wrong way.


F# does have type classes, they're just called interfaces.

https://msdn.microsoft.com/en-us/visualfsharpdocs/conceptual...


Type classes are quite different from interfaces. How would you encode the Eq typeclass in F#? .Net has the IEqualityComparer<T> interface but you need to manually pass that around (unlike Eq instances) and you also lose the global uniqueness property.


You don't have to rely on the built in interfaces provided by .NET, you can create your own. Just like in Haskell in F# you can use pattern matching against types to define which of the equality operators to use.

Also, I'm not sure what you mean by "manually pass that around". When you define a class in Haskell that inherits from a typeclass you reference that typeclass in the header of the new class. You follow the same approach in F# with interfaces.


By 'pass around', I mean pass around instances, not definitions. You could define your own Eq interface in F#

  type IEq<'a> =
    abstract member eq: 'a -> 'a -> bool
but you then need to explicitly pass instances of this interface around into every method that requires it e.g.

  let allEq (s: 'a seq) (eq: IEq<'a>) = ...
whereas the haskell version would receive the Eq instance for the input type implicitly.

Typeclass instances are globally unique for each type, which cannot be enforced with the interface solution. If you have an ordered map type, you can be sure the Ord instance used for insertion is the same that is used for retrieval. With the interface approach, clients cannot know which instance to use since there could be multiple implementations. The Haskell approach has its own problems, such as the proliferation of newtype wrappers to manage the dispatch mechanism.

Interfaces also hide the representation of one of their arguments (the receiver) whereas typeclasses are just a dictionary of functions.


I'm not sure I understand all of what you've said, as I'm not familiar with Haskell, but there are at least some Haskell programmers have recognised the similarities between type classes and interfaces. Do you disagree with any of the following?

https://wiki.haskell.org/OOP_vs_type_classes#Type_classes_ar...

"Type classes are like interfaces/abstract classes, not classes itself

There is no inheritance and data fields (so type classes are more like interfaces than classes)....

For those more familiar with Java/C# rather than C++, type classes resemble interfaces more than the classes. In fact, the generics in those languages capture the notion of parametric polymorphism (but Haskell is a language that takes parametric polymorphism quite seriously, so you can expect a fair amount of type gymnastics when dealing with Haskell), so more precisely, type classes are like generic interfaces.

Why interface, and not class? Mostly because type classes do not implement the methods themselves, they just guarantee that the actual types that instantiate the type class will implement specific methods. So the types are like classes in Java/C#.

One added twist: type classes can decide to provide default implementation of some methods (using other methods). You would say, then they are sort of like abstract classes. Right. But at the same time, you cannot extend (inherit) multiple abstract classes, can you?

So a type class is sort of like a contract: "any type that instantiates this type class will have the following functions defined on them..." but with the added advantage that you have type parameters built-in, so:

  class Eq a where
    (==) :: a -> a -> Bool
    (/=) :: a -> a -> Bool
    -- let's just implement one function in terms of the other
    x /= y = not (x == y)
is, in a Java-like language:

  interface Eq<A> {

    boolean equal(A that);
    boolean notEqual(A that) { 
       // default, can be overriden
       return !equal(that); 
    } 
  }
And the "instance TypeClass ParticularInstance where ..." definition means "ParticularInstance implements TypeClass { ... }", now, multiple parameter type classes, of course, cannot be interpreted this way."


They explicitly said "an ML derivative that's not OCaml". It's not a big leap from that statement to "neither OCaml nor a Caml derivative" given the similarities between the languages. I'm really not at all surprised that if they want to discount OCaml as a successor ML, they'd want to discount F# as well, given the close relationship between the two. Like @hroman, I too was rather puzzled by your initial statement.


I'm sort of sick of hearing that OCaml has crappy or crufty syntax. I like OCaml's syntax. There is just a sea of useless algol brackets in so many languages. I was sort of sad that Rust fell victim to the damn bracket. At times I don't even think Scala is that much more succinct than modern Java 8 (ala bracket indentation fun).

I remember years ago (15 years.. jesus I'm old) discovering OCaml and I couldn't believe how terse the language was for producing native code. If anything I don't like about OCaml syntax is that it actually has an enormous amount of syntactic sugar.


Was OCaml was your first ML language? It seems that most of the people who find OCaml crufty used Standard ML before OCaml.


Guilty as charged.. I did learn OCaml first and from that official green HTML documentation which still appears to be green after 16 years :).

My complaint with OCaml was OCamlp and the tedium of creating modules and functors. While AdHoc poly (aka type classes) is not as flexible it is IMO easier to understand, generally less verbose and slightly more elegant than OCaml modules. I'm glad they added first class modules as I recall wanting something like that a long time ago.


For what it's worth, I think OCaml's syntax is one of its weakest points (not to mention syntax extensions...) and I have been writing OCaml 3 years longer than I've been writing Standard ML.


Well yes I agree if you compare OCaml to Standard ML its syntax is not as good and I do prefer Standard ML over it. However I prefer OCaml over Java, Javascript, Scala (and the bazillion other brace block languages that are the same), and yes even Haskell.


F# doesn't even have modules. Not really in the SML spirit—it's like if you combined Classic/LCF ML from the 1970s with C#.


In the context of ML, what are modules and why are they useful?


Poly/ML isn't an SML derivative, per se. It's an implementation of Standard ML (and a damn fine one at that).


Many icons are well known and work well.

The back, forward, reload buttons are more usable as icons than text.

When not overused, operators are similarly more usable than verbose English names.


Totally agree. There was a great example on /r/haskell the other day.

https://www.reddit.com/r/haskell/comments/4sdkch/haskel_newb...

Operators are certainly overused in Haskell, but sometimes they make something so much more readable.


Holy cow, poly/ml looks outstanding, threads, sockets, signals, a ffi, a lot of things I've been missing in SML all these years. Is there support for unicode in the string library? How's the generated code performance wise? I will definitely keep an eye on this project.


Poly/ML produces excellent code. It's probably the second most performant SML implementation after MLton.


Does it produce native executables that are easy to distribute?


On platforms for which it can produce native code, yes. The compiler will produce typical object files which can then be linked with the usual linker. For other platforms it uses a byte compiler.


Interesting, thanks. Worth noting that every Cambridge compsci undergrad has to learn SML. I ended up moving onto OCaml and Scala.


Same as compsci students at TU Munich, if Prof. Rybalchenko does the intro to functional programming course.

I really enjoyed it and found it much better suited for students than other languages, especially with the book by Gert Smolka.


Do you have a link to "that book?"



  > operators (not named functions) are to programming
  > languages as icon-only buttons are to web pages;
  > they are completely unusable.
I see ( ) ; . you are using already. Latin letters are gibberish to people who don't use it.


I wrote some Scala just today:

  val list = a +: l :+ b
And I knew I had to put in a comment because that stuff always makes my eyes cross over when I come back to it.


Don't know Scala, but I'd assume that `+:` is prepend to list and `:+` is append to list.


You'd be correct.

But they're just method calls, both defined on the class of l. It is a little weird.


I can see the argument for terseness in source, particularly in domains where the terseness in code reflects well-understood shorthand in the actual problem space. But stuff like that makes me itch, to be honest.


The alternative would be something like

  l.prepend(a).append(b)
Horrible. Ghastly. Can't see anybody tolerating a language that looked like that.. /s


It gets even worse. Because Scala has infix syntax for method calls, you can do

    l prepend a append b


What? Mutating a list? DISGUSTING!


It's not mutating, its returning a new list with elements prepended and appended.


Don't know Scala but why wouldn't it be

a.append(l).append(b)

?


That would only work if a was itself a list..


  もっと練習  ⍝ Practice more  NB. ⍝ is a symbol for comment.
  /* NB. is for comment, too. */
  // Anything inside /* */ is comment, too.
  #  // starts a comment, too.


I don't know Scala and I have no idea of what +: :+ means, which at first is not a good sign (think about onboarding.) Then I remembered that many mainstream languages have the

    a ? b : c
construct which maybe was equally puzzling when it was introduced by CPL in 1963.


They're operators that cons an element on to a list. They're both defined on the List class, but differ in associativity because they start/end in a colon.

"a +: l" calls the +: method on l with a as its argument and returns a list with a added to the start, "l :+ b" calls the :+ method on l with b as its argument and returns a list with b added to the end. "a +: l :+ b" (parsed as "(a +: l) :+ b") therefore returns a copy of l with a added to the start and b added to the end.

This is user definable, you can make operators whichever way you like (and start them with : if you want them to be right associative).

It's very flexible and you do sort of get used to libraries using it, but I'm not entirely sure that getting used to something always means it's good.

(TBH though, I use the ternary operator constantly and think nothing of it.)


Scala can be extended by users with stuff like that.


The fact that C-style ternary is hard to pick up doesn't really excuse this kind of thing in new languages.


Learning SML isn't going to help as much with Haskell as you might think. The others, yes.


I have ~4 years experience writing OCaml, and ~1 year experience writing Standard ML. I also once did contracting for a Play app in Scala for 3 months. A month ago, I started looking into Haskell for the first time for another side project and was immediately able to pick it up due to how similar it is to OCaml and Standard ML. In particular, the type syntax and function declarations are similar; understanding monads in SML/OCaml helps understand... everything in Haskell; and understanding of modules/functors/signatures transfers indirectly to type classes as well. (Here is a paper going into even more detail [0].) It felt like Haskell has some of the syntactic sugar I always wished Standard ML had as I learned its limitations.

[0] http://www.cse.unsw.edu.au/~chak/papers/modules-classes.pdf


If you already know SML or OCaml, you'll pick up Haskell easier, but if you don't know them and want to learn Haskell, you're not taking a shortcut by learning SML or OCaml first.


Although I happened to learn OCaml first, I am actually arguing that learning SML is a better way to learn the concepts behind tremendously more complex and less user-friendly languages like OCaml and Haskell. I don't know if I'd say it's a shortcut, but it's pretty natural to learn by studying a simpler (perhaps historic) topic before studying a more modern and complex one.


Its whatever works for every person, but I'll throw in my own experiences and say, that by taking a detour into Ocaml I was actually greatly aided in understanding Haskell. And that having spent a great deal of time with a number of Lisps. I had grabbed a copy of RWH, dug into it, been a little defeated at first, took a studious detour through RWOcaml and have returned to Haskell with a clearer view. Again, to each their own, my own experience was actually the opposite of your statement.


I'm just glad to a an "ML" article that's referring to MetaLanguage and not Machine Learning.


I always took it to be Milner Language.

Prof Milner was my first CS lecturer, many years ago. Ironically the language for that course was Pascal.


That is amazing, how was he as a lecturer?


Well, that first course was very basic and open to all students, and I didn't know who he was. Just seemed like a typical lecturer way down the front of a big hall.

A couple of years later, he taught my class of ~20 his Calculus of Communicating Systems; I think it was the first time he tried it out on undergraduates. He was incredibly kind and patient; really interested to find out which parts of the explanation didn't work, and how he could get it across better.


* glad to see an "ML" article ...


> Dependent types are the future

I think so too. Having a solver fill in my program from the proof obligations is way too amazing. I feel like there could be a connection from high-level specification -> implementation either by proof obligation or possibly synthesis via this route.

Plus I like ML/OCaml and would be happy to see more of it in the world.


Agreed on dependent type, and I also love ML syntax more than haskell(yes I don't like indentation sensitive language). BTW I suggest you give FStar a try, it has dependent type and OCaml/F# like syntax and support theorem proving


You don't have to use indentation for nesting in Haskell. Haskell's syntax is actually defined with curly braces and semicolons and you're free to use them. It's just smart enough to add missing curly braces and semicolons at the right places according to indentation when they're missing.


Yeah, you're right. But almost all of the community uses indentation which defined as layout in Haskell2010 Language Report instead of semicolons and curly braces


I was taught functional programming through SML in university two years ago. I have never had my brain twisted with so many interesting and clever concepts - it was one of the most valuable semesters I had, and my favourite class.

Go learn functional programming if you haven't, it will force you to look at problem with a new set of eyes!


okay


I revere ML and loved using it back in the day, but I code now in Haskell and am even happier. I like never having to figure out what parts of a program or library are referentially transparent. Why would I ever want to use an impure language again?


Maybe because you need to write some performant code?


I write fast code instead.


What do you think the difference is between "performant" and "fast"?


"fast" is in my dictionary.


Thanks for pointing out that "performant" is not in any english dictionary! (http://weblogs.asp.net/jongalloway/performant-isn-t-a-word) Didn't know that.

Besides that, your "fast" code will not be as fast as it can be if you are only relying on purely functional code, at least on current architectures.


Do be fair, he said "impure language" and not "impure code".

"Looks like we need to let the scholars know - there are 18,300 uses of the non-word "performant" in scholarly papers" <- If that's not sarcasm, something is wrong. Performant is a word!


It is a word, just not an English one it seems! It certainly is a German word. That might explain a lot ;-) It might also explain the many occurrences, as there are many Germans writing papers in English.


It would be nice if the author provided some actual evidence for sweeping claims like "modules are far better than objects" and "the world is converging on ML as the language of choice". If there really is evidence, that would be great to hear about. If there isn't then these statements seem a bit self-serving.


For newbies (like me): Apparently in this context, ML abbreviates meta language, not machine language or machine learning.


Can someone provide me with references for a succinct, lucid introduction to the ML module system and what problems it solves, and what shortcomings is has that are (partially?-)resolved by later variants?


Danny Gratzer wrote about this a while back:

http://jozefg.bitbucket.org/posts/2015-01-08-modules.html




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

Search: