[HN Gopher] What was wrong with SML?
___________________________________________________________________
What was wrong with SML?
Author : rdpintqogeogsaa
Score : 63 points
Date : 2022-04-30 18:10 UTC (4 hours ago)
(HTM) web link (blog.plover.com)
(TXT) w3m dump (blog.plover.com)
| eatonphil wrote:
| I mentioned to Mark when I saw this, and he noted it in the
| addendum at the end, that calling Standard ML dead is a bit too
| much. I've written recently [0] about how active it surprisingly
| is.
|
| I also disagree that its failure to "succeed" has anything to do
| with syntax or semantics and solely that it doesn't have a Jane
| Street or any company publicly behind it.
|
| [0] https://notes.eatonphil.com/standard-ml-in-2020.html
| porcoda wrote:
| I don't think it succeeded or failed. Languages don't need to
| be wildly popular in industry to be valuable. I personally like
| that industry ignores SML. Even for Ocaml I don't use the Jane
| street core: I just use the stock language since it's small and
| stable. I like that Jane street helps improve the core compiler
| though.
| mjd wrote:
| I would like to point out that the article does not use the
| words "succeed" or "fail", and makes no claim about whether SML
| "succeeded" or "failed". Indeed I don't think that is a useful
| question to ask.
|
| My article was trying to address a much less nebulous issue:
| what problems did I personally see with SML in the mid 1990s
| that let me to abandon it at that time.
| eatonphil wrote:
| Sorry, I didn't mean to put words in your mouth. I may just
| have gotten the wrong impression of your intent.
|
| Any criticism of any language is valid and good to have!
| fanf2 wrote:
| There was a history of Standard ML published as part of HOPL4 a
| couple of years ago - https://dl.acm.org/doi/10.1145/3386336 I
| was particularly interested by the more recent history, after SML
| '97, where there was plenty of interest in improving the language
| and its library, but Milner insisted that there would be no
| further changes, and the Definition was non-free so the others
| could not build on it. (It has since become Free though its
| source code was lost.)
|
| Despite that there is/was an SML Basis Library project, and a
| Successor ML project, but it looks like even the die hard fans
| have drifted away https://smlfamily.github.io/
| bzxcvbn wrote:
| I'm not really convinced by the author's first example. While an
| element of type bool is an instance of type a, an element of type
| bool -> bool is _not_ an instance of type a - > a.
|
| The issue is precisely an issue of variance, which is mentioned
| in reference to Scala, but somehow it's glossed over. The type a
| -> a is covariant in its second argument, but contravariant in
| its first argument. As a result, you cannot "specialize" it to
| bool -> bool, because specialization is really another name for
| covariance.
|
| Another name for contravariance is "generalization". If you ask
| for something of type "bool -> b", and someone provides you with
| some function f of type "a -> b", then you're happy. The map f is
| indeed an instance of "bool -> b": it can eat anything, so it can
| eat booleans. But with type a -> a, you cannot do what I just
| did: type "a" is already the most general one, and you cannot do
| better.
|
| If SML accepted something of type "bool -> bool" for an instance
| of type "a -> a", then it was a fundamental error. But this
| doesn't mean that the whole thing should have been thrown out and
| replaced with monads. In fact, I don't really get how monads have
| anything to do with the problem at hand. If Haskell can prevent
| the following code, then I don't see why SML couldn't have
| prevented the authors' code: do m <- STRef id
| m <- not m 42
| pjmlp wrote:
| What was wrong is not having a killer application or an industry
| giant pushing it.
|
| Grammar and language semantic are details regarding language
| adoption.
| eatonphil wrote:
| Yup, adoption has nothing to do with being a sensible language.
| More often it seems to be completely inversely related.
| exikyut wrote:
| What are some sensible (coherent, load-bearing, force-
| multiplying etc) tools that have terrible adoption?
|
| Unreasonably open-ended question (suppose the scope is ML, or
| perhaps FP in general, or maybe even wider) - but I'm very
| curious.
| pharmakom wrote:
| I would say F#. It has most things you could want:
|
| - Proper functional programming support
|
| - Fast enough runtime
|
| - Cross-platform and open-source
|
| - Mainstream ecosystem
|
| - Large corporate backer
|
| - Compile to JS
|
| - Commercial and open-source tooling options
|
| ... and yet C# is far more popular. This is because
| language adoption is driven by existing user base and other
| network effects NOT the quality of the language itself.
| youerbt wrote:
| TLA+ or Nix comes to mind. By some notion of terrible I
| guess.
| eatonphil wrote:
| Google "worse is better". :)
| Athas wrote:
| > Haskell's primary solution to this is to burn it all to the
| ground. Mutation doesn't cause any type problems because there
| isn't any.
|
| This is true, but I think it is also misleading. Haskell has the
| same problem if you use unsafePerformIO to create a polymorphic
| IORef at top level. You can then use this IORef to subvert the
| type system. I think this is something many Haskell programmers
| are not fully aware of: unsafePerformIO doesn't just break
| referential transparency; it can also fundamentally break memory
| safety. Now, you may say that unsafePerformIO is obviously unsafe
| (it's in the name!) and should never be used. But if you look at
| many foundational Haskell libraries, you will find that they use
| unsafePerformIO or similar functions internally, usually for
| performance reasons. What are the rules that govern safe usage of
| unsafePerformIO? As far as I can determine, these rules are
| basically just GHC implementation details, and people often get
| them wrong. And if you break these rules, you don't just get a
| function that doesn't do what you expected - you may have
| subverted memory safety entirely.
|
| I think this is an interesting conundrum. Haskell makes much
| stronger promises than SML, but if you break the rules, all bets
| are completely off.
| throwamon wrote:
| A bit off-topic, but could someone ELI5 what a lattice is in this
| context?
| mjd wrote:
| If you have two types, there should be a single type that
| "joins" them, in the sense that you can understand both of the
| original types as somehow being special cases of the join type.
|
| A join is not necessarily a union, since the representations of
| the three types might be completely different, and also because
| the third type might contain many values that don't correspond
| to anything in the two original types. (It might be much bigger
| than the union.)
|
| Mathematical lattices must also have "meets", which are like
| joins except down instead of up. I'm not sure that meets are as
| important as joins in this context.
| layer8 wrote:
| It refers to https://en.m.wikipedia.org/wiki/Lattice_(order),
| with the elements of the lattice being the arithmetic types and
| the order relation being the subtyping relation here. Given any
| two types in the lattice, the lattice property then guarantees
| that there exists a unique common (least) supertype (aka upper
| bound, supremum) of the two types. Which means you can apply
| the binary operation (e.g. addition) as defined for that common
| supertype.
| chombier wrote:
| I think this refers to a system of types in which for any two
| types there is also an union type and an intersection type in
| the lattice.
| tialaramex wrote:
| SML was the First Language used for the Computer Science degree I
| took. I felt at that time, and continue to feel years later (that
| degree course now teaches Java as First Language) that this was a
| good decision _despite_ the fact that most graduates don 't end
| up using SML to write anything.
|
| In the course of my education I experienced some things which I'm
| convinced are a _bad idea_ even though they worked out OK for me
| such as selective education (whole schools only for "talented"
| children) and single sex secondary education, but SML as First
| Language is not one of those things. It worked well for me _and_
| I 'm convinced it's a good idea even though I would not advocate
| writing new real world projects in SML unless you've got some
| very particular reason.
| chombier wrote:
| > Scala has a very different solution to this problem, called
| covariant and contravariant traits.
|
| I thought Scala had an even stricter value restriction than ML,
| where only function/methods may get a polymorphic type?
| eatonphil wrote:
| For folks interested in learning Standard ML, check out /r/sml
| [0] and the sticky post [1] with a getting started guide.
|
| [0] http://reddit.com/r/sml
|
| [1]
| https://www.reddit.com/r/sml/comments/qyy2gs/getting_started...
| jasonhansel wrote:
| IMHO Haskell's lazy evaluation has some significant disadvantages
| compared to SML's strict evaluation. In particular, lazy
| evaluation makes it difficult to find the performance bottlenecks
| in a particular piece of code or to determine the time complexity
| of an algorithm just by reading it.
|
| Furthermore, subtle changes in how a function is written (for
| instance, making a multiplication function not evaluate the right
| operand if the left operand is zero) can cause wildly unexpected
| performance changes in that function's callers. In effect, the
| performance of a function is no longer just determined by that
| function's structure and by the function calls it contains;
| performance of one function now depends heavily on the
| implementation details of others and the context in which that
| function is used.
|
| Granted, any optimizing compiler can have this effect, but it's
| rarely noticeable in strictly-evaluated languages, where at least
| to some extent the order of evaluation must correspond to the
| structure of the code.
| porcoda wrote:
| I still actively use SML - mlton or smlnj usually, polyml too.
| I'm aware of the issues raised in this post but haven't ever
| found them to be a source of much headache. To be honest, the
| biggest headache is moving between compilers and their different
| build processes. Other than that, the fact that the language
| isn't really changing is a big attraction for me.
|
| CakeML is also a very cool project in SML land.
| shpongled wrote:
| SML is one of my favorite languages (I've been (very) slowly
| writing a compiler & language server for it).
|
| Sure, it has some warts/differences compared to newer languages -
| we have moved towards traits/typeclasses/etc, and I wish I could
| just write #[derive(Debug) - but I feel that SML fits in a very
| unique spot for programming languages. It's extremely simple, yet
| still powerful and expressive. I hope we will see continued work
| on SML/Successor ML descendants (like 1ML, etc), because I think
| there's still potential there
|
| I think some updated language tooling would dramatically help.
| jaytaylor wrote:
| Is your development progress taking place in the open? (e.g.
| GitHub or somewhere similar)
|
| It sounds like a cool project and I'd love to see it! And even
| have the option to open a PR and help ;)
| eatonphil wrote:
| Yes, please share or open-source it even if it's not done!
| shpongled wrote:
| You have already linked to it :)
| shpongled wrote:
| I have the compiler on GitHub [1] - I just started working on
| it again after a 2-year hiatus (to finish my PhD).
|
| As for language-server, I'm currently sketching out some
| plans to use SMLnj's "Visible Compiler" feature, since that
| seems the easiest path forward. I have a half-baked language-
| server based on MLton's def-use output, but it's too unstable
| to share. I am planning to make some progress on the
| language-server in the next couple weeks.
|
| [1] You'll notice it's just a fragment of the language for
| now, and only half-implemented.
| https://github.com/SomewhatML/sml-compiler and
| https://github.com/SomewhatML/sml-analyzer (again for a
| fragment of SML)
| bobbylarrybobby wrote:
| > In Structure and Interpretation of Computer Programs, Abelson
| and Sussman describe an arithmetic system in which the arithmetic
| types form an explicit lattice. Every type comes with a
| "promotion" function to promote it to a type higher up in the
| lattice. When values of different types are added, each value is
| promoted, perhaps repeatedly, until the two values are the same
| type, which is the lattice join of the two original types. I've
| never used anything like this and don't know how well it works in
| practice, but it seems like a plausible approach, one which works
| the way we usually think about numbers, and understands that it
| can add a float to a Gaussian integer by construing both of them
| as complex numbers.
|
| Julia uses this in pretty much all of its math functions and
| probably elsewhere as well, and it works unbelievably well. The
| type promotion system makes math Just Work, even (and especially)
| in the face of different-sized numbers. The result is that 99.9%
| of the time you simply don't have to think about the types of
| your numbers. Here are some examples from the docs:
| julia> promote_type(Int64, Float64) Float64
| julia> promote_type(Int32, Int64) Int64 julia>
| promote_type(Float32, BigInt) BigFloat julia>
| promote_type(Int16, Float16) Float16 julia>
| promote_type(Int64, Float16) Float16 julia>
| promote_type(Int8, UInt16) UInt16
|
| And not only are types promoted, but in well-typed Julia code,
| the deduction of promotion types happens at compile time instead
| of runtime, so there is almost no performance cost to this
| either.
___________________________________________________________________
(page generated 2022-04-30 23:00 UTC)