Live data from Hacker News

Standard ML in 2020

notes.eatonphil.com

61–70 of 125 posts

Re: Standard ML in 2020

#61
post #56

Earlier quoted context omitted.

> I find the `ref` syntax of SML much nicer to use than the mutable record syntax in Ocaml. Maybe I'm missing something in SML, but OCaml has `ref` as well and it works just like SML's? let x = ref 0 x := 12 print_int !x > SML strings are immutable which lends itself to a lot of potential optimizations (and there's always byte arrays if you actually need to mutate). OCaml's strings are also immutable. They have been…

You are correct that Ocaml has a ref type (though I believe it is actually a special case of a mutable record with one field). Most stuff I've run into uses mutable records more than refs (granted, I'm hardly deep into the Ocaml way of doing things). There is a small difference between an immutable record of which one property is a reference to changing data and a mutable record where the record itself changes. I pre…

> You are correct that Ocaml has a ref type (though I believe it is actually a special case of a mutable record with one field). > There is a small difference between an immutable record of which one property is a reference to changing data and a mutable record where the record itself changes. I prefer the first though I realize this is mostly preference.

In OCaml ref is defined as

  type nonrec 'a ref = 'a ref = { mutable contents : 'a }
so it is an immutable record which contains one item which is mutable.

> In any case, the idea of outright changing a formerly mutable structure to an immutable one would be unthinkable in most languages due to all the breakages it is likely to cause.

I agree with you. I started using OCaml in 2018 but I believe many linux distributions stayed on OCaml 4.05 (the release before safe-string was default) for a while because of breakages.

Re: Standard ML in 2020

#62
post #58
post #34

Earlier quoted context omitted.

The profusion of Category-theoric abstractions and some of the more recent purely functional norms in Haskell are like the PhD-level version of `AbstractVisitorContextFactoryBuilder` which, aside from all the unnecessary cognitive load, lead to enormous dependency graphs of the npm variety. Personally, I wonder if uniqueness types in languages like the sadly forgotten Clean (a close relative of Haskell) would have be…

I don't think there's a way to not use monads, because a ton of everyday things just work in a monadic way, things like lists, or statement sequences in presence of exceptions. I think it's wiser to admit and use these properties instead of ignoring them. Ignoring maths that underlie computation when writing software is like ignoring math that underlies mechanics when building houses: for some time you can get by, bu…

I recently read a blog post by someone who worked as a carpenter for a summer. He said he disliked the saying “measure twice, cut once” because actual carpenters avoid measuring as much as possible! For example, to make a staircase, you could try using simple trig to calculate the lengths of the board, angle of stair cut outs, step widths, etc. But that would all be wasted effort because you can’t actually measure and cut wood to sufficient precision. Instead, you need to just get rough measurements and then use various “cheats” so the measurements don’t matter, like using a jig to cut the parallel boards at exactly the same length (whatever it turns out to be).

Analogy to monads is this: yes, there are mathematical formalisms that can describe complex systems. Everything can be described by math! That’s literally its one job. But will the formalisms actually help you when the job you’re doing has insufficient achievable precision (eg finding market fit for a website)?

Re: Standard ML in 2020

#63
post #60

I am designing a language based on OCaml/Standard ML, what are some of the problems present in these languages that can be fixed by a new design without being constrained by a spec or backwards compatibility?

Avoid Ocaml's syntax soup. I'd also avoid making it easy to bolt on a bunch of syntactic extensions ala camlp4

Keep your standard library standard.

Module Typeclasses

One, immutable string type. Make it UTF-32 by default (you can always store in a smaller format behind the scenes and extend). Make it multiline. Allow variable interpolation (typeclasses should help).

SML structural typing and anonymous records are better than nominal typing.

Skip on syntax bloat like named parameters.

Overload your math operators instead of having special float operators like Ocaml (once again, typeclasses make this much easier).

Rethink imports. F# requires you to add tons of files in the correct order to an XML. Ocaml imports all the things from the folder and blows up if you use the same module name twice. SML needs to standardize `use`. I'd recommend something like JS static import statements.

If you build good documentation, good compiler errors and good tooling, more people coming to the project and help make a better compiler (a reversal of this is the big issue with SML right now in my opinion).

Re: Standard ML in 2020

#64
post #25

Earlier quoted context omitted.

> I'm also pretty jealous of OCaml's modular implicits, Have modular implicits already been implemented? I thought they were still trying to figure out the details of the resolution...

Ah, well as with most OCaml planned features I gave up on waiting. Maybe they haven't finished this one.

What ocaml got recently, though, is do notation in the form of "let operators". It's very handy for applicative or monadic style.

Re: Standard ML in 2020

#65
post #58

Earlier quoted context omitted.

I don't think there's a way to not use monads, because a ton of everyday things just work in a monadic way, things like lists, or statement sequences in presence of exceptions. I think it's wiser to admit and use these properties instead of ignoring them. Ignoring maths that underlie computation when writing software is like ignoring math that underlies mechanics when building houses: for some time you can get by, bu…

I recently read a blog post by someone who worked as a carpenter for a summer. He said he disliked the saying “measure twice, cut once” because actual carpenters avoid measuring as much as possible! For example, to make a staircase, you could try using simple trig to calculate the lengths of the board, angle of stair cut outs, step widths, etc. But that would all be wasted effort because you can’t actually measure an…

I think that the metaphor leaks badly. Finding market fit is like deciding on the general shape of the staircase. Execution of whatever design still needs the stairway to be strong and reliable all the same.

Writing code is a much more precise activity that cutting wood. Using "cheats" can get you somewhere, but due to the precise nature of the machine logic, the contraption is guaranteed to bend and break where it does not precisely fit, and shaving off the offending 1/8" is usually not easy, even if possible.

Re: Standard ML in 2020

#66
post #35

As someone reasonably versed in OCaml but knows nothing about SML, what are primary differences? Given that OCaml has much better tooling and more of a community, what draws people to SML still?

SML records are structurally typed and may be anonymous which makes a lot of things easier to write. I've heard Ocaml has been attempting to tack that on, but that leads to the next point of Ocaml syntax being a complete mess. Ocaml needs keyword arguments, but in SML, structural typing gives named arguments without all the extra syntax. I find the `ref` syntax of SML much nicer to use than the mutable record syntax…

> Module Typeclasses should keep typeclasses from happening everywhere (looking at you Haskell) while still allowing them to be used for more than equality.

I was under impression that Haskell's typeclasses plus a couple of most common extensions minus the namespace pollution are pretty much equivalent to ML modules+functors, so could you elaborate how exactly that should work?

Re: Standard ML in 2020

#67
post #55
post #39

Earlier quoted context omitted.

Are you familiar with unsafe IO? It's used pervasively in low-level code because the idealism of monads just doesn't cut it. In my opinion, this proves that the pragmatism of side effects is a necessary evil for actually getting things done in a performant way. Lazy evaluation has the same kind of issues. Most humans don't think that way, so performance suffers. This may be a universal problem as in my experience, Ha…

> Are you familiar with unsafe IO? > It's used pervasively in low-level code because the idealism of monads just doesn't cut it. In my opinion, this proves that the pragmatism of side effects is a necessary evil for actually getting things done in a performant way. It seems like you aren't very familiar with the ways Haskell programmers deal with side effects and mutation. UnsafePerformIo is sometimes needed, and the…

Wait, I thought that lazy io (e.g. getting a lazy string back from "reading" a file, which triggers subsequent reads when you access it) was widely considered bad and a mistake.

Re: Standard ML in 2020

#68
post #58

Earlier quoted context omitted.

I don't think there's a way to not use monads, because a ton of everyday things just work in a monadic way, things like lists, or statement sequences in presence of exceptions. I think it's wiser to admit and use these properties instead of ignoring them. Ignoring maths that underlie computation when writing software is like ignoring math that underlies mechanics when building houses: for some time you can get by, bu…

I recently read a blog post by someone who worked as a carpenter for a summer. He said he disliked the saying “measure twice, cut once” because actual carpenters avoid measuring as much as possible! For example, to make a staircase, you could try using simple trig to calculate the lengths of the board, angle of stair cut outs, step widths, etc. But that would all be wasted effort because you can’t actually measure an…

> But will the formalisms actually help you when the job you’re doing has insufficient achievable precision (eg finding market fit for a website)?

In my experience, this is exactly the problem Haskell's core abstractions—monads among them—help with!

What do you need when you're trying to find product-market fit? Fast iteration. What do Haskell's type system and effect tracking (ie monads) help with? Making changes to your code quickly and with confidence.

Haskell provides simple mathematically inspired tools that:

1. Make clean, well-factored code the path of least resistance.

2. Provide high-level, reusable libraries that keep your code expressive and easy to read at a glance despite the static types and effect tracking.

3. Give you guardrails to change your code in systematic ways that you know will not break the logic in a wide range of ways.

If I had a problem where I'd need to go through dozens of iterations before finding a good solution—and if libraries were not a consideration—I would choose Haskell over, say, Python any day. And I say this as someone who writes a lot of Python professionally these days. (Curse library availability!)

Honestly, Haskell has a reputation of providing really complicated tools that make your code really safe—and I think that's totally backwards. Haskell isn't safe in the sense that you would want for, say, aeronautical applications; Haskell programs can go wrong in a lot of ways that you can't prevent without extensive testing or formal verification and, in practice, Haskell isn't substantially easier to formally verify than other languages. And, on the flipside, Haskell's abstractions really aren't complicated, they're just different (and abstract). Monads aren't interesting because they do a lot; they're interesting because they only do a pretty small amount in a way that captures repeating patterns across a really wide range of types that we work with all the time (from promises to lists to nullable values).

Instead, what Haskell does is provide simple tools that do a "pretty good" job of catching common errors, the kind of bugs that waste a lot of testing and debugging time in run-of-the-mill Python codebases. This makes iteration faster rather than slower because you get feedback on whole classes of bugs immediately from your code, without needing to catch the bug in your tests or spot the bug in production.

Re: Standard ML in 2020

#69
post #67
post #55

Earlier quoted context omitted.

> Are you familiar with unsafe IO? > It's used pervasively in low-level code because the idealism of monads just doesn't cut it. In my opinion, this proves that the pragmatism of side effects is a necessary evil for actually getting things done in a performant way. It seems like you aren't very familiar with the ways Haskell programmers deal with side effects and mutation. UnsafePerformIo is sometimes needed, and the…

Wait, I thought that lazy io (e.g. getting a lazy string back from "reading" a file, which triggers subsequent reads when you access it) was widely considered bad and a mistake.

Yes, that's true. I thought about mentioning that in my comment, but it seemed like a bit of a digression and it was already getting a bit wordy.

Anyways, the problem is that you might open a file, read it into a string, close the file, and then pass the string into some pure function. The problem is that the file was closed before it was lazily read, and so the string contents don't get populated correctly; you get the empty string instead, or whatever was lazily read before the file was closed.

That was a design oversight from the early days. If you know about it, it's pretty easy to work around it in simple applications. There are some more modern libraries for doing file IO in a safer way, but I haven't used them and don't really know what the details are.

Post reply on HN