Live data from Hacker News

Functional languages should be so much better at mutation than they are

cohost.org

131–140 of 188 posts

Re: Functional languages should be so much better at mutation than they are

#131
post #41

Earlier quoted context omitted.

> This is one example why your statement above is not true. You are misreading my comment. I’m not intentionally contradicting myself in two paragraphs next to each other (I’m not always the brightest but still). The point is that contrary to what the article states ML developers are not avoiding mutations because they are uneasy to use but because they trust their compiler when they know it will do good. Proof is th…

> The point is that contrary to what the article states ML developers are not avoiding mutations because they are uneasy to use but because they trust their compiler when they know it will do good. Proof is that in other case they will use mutations when it makes sense to do so because the compiler does not do a good job. It will do a good job, yes. Will it do the best possible job compared to some other algorithm or…

No, not this. You are doing a map. A traversal of a data collection is not a map but a fold. The exemple in the article is specifically about collection which you would do by consing to a list (mostly free once optimised) in a fold_left (so tail call optimised to a loop). See my other comment.

Also, List.map is not optimised in Ocaml. It uses a naive implementation and not a tail call. You have to use rev_map to get good perf.

Re: Functional languages should be so much better at mutation than they are

#132
post #38

Earlier quoted context omitted.

One thing that many people miss is that Haskell's monadic style is a direct consequence of lazy evaluation. It all started because they thought lazyness was nice, and wanted to make a language that brought that front and center. But then they found out that they had to come up with a new way to do side-effects, because traditional side-effects don't work when the order of evaluation is unpredictable.

I think this is historically wrong. Monads didn’t land until later in Haskell, no?

They did, but they also did land explicitly to make I/O suck less in lazily evaluated language instead of magic main function signature working to provide explicit ordering.

There's a reason why Monads aren't exactly monadic and why IO was the original monad in GHC -as well as why non-lazy, non-super-pure languages never really go for Monads

Re: Functional languages should be so much better at mutation than they are

#133
post #95
post #38

Earlier quoted context omitted.

One thing that many people miss is that Haskell's monadic style is a direct consequence of lazy evaluation. It all started because they thought lazyness was nice, and wanted to make a language that brought that front and center. But then they found out that they had to come up with a new way to do side-effects, because traditional side-effects don't work when the order of evaluation is unpredictable.

> One thing that many people miss is that Haskell's monadic style is a direct consequence of lazy evaluation. It all started because they thought lazyness was nice, and wanted to make a language that brought that front and center. But then they found out that they had to come up with a new way to do side-effects, because traditional side-effects don't work when the order of evaluation is unpredictable. But this is no…

Haskell showed that a monadic bind is a nice solution to chaining together IO operations once you have boxed them inside their own type and boxing IO operations inside their own type was a nice solution to the issue arising from being lazy by default.

Haskell was actually widely successful in showing that, no doubt about that.

Re: Functional languages should be so much better at mutation than they are

#134

The article utterly falls apart in its first paragraph where it itself acknowledges that the whole ML family including Ocaml has perfect support for mutation, rightfully assume most Ocaml programmers would choose to not use it most of the time but then assume incorrectly that it’s because the language makes it somehow uneasy. It’s not. It’s just that mutation is very rarely optimal. Even the exemple given fails: > Fo…

> The article utterly falls apart in its first paragraph where it itself acknowledges that the whole ML family including Ocaml has perfect support for mutation Was the article updated since you wrote this? I don’t see the text you’re referring to. > Well, no, this is straight confusion between what’s expressed by the program and what’s compiled. You’re getting at an important point here, but then you seem to fall int…

> Monads started out as a way to represent the semantics of effects in a mathematical context

I mean, that statement is untrue but even then I wasn't talking about monads here (monads are not a convoluted trick as far I'm concerned). I was thinking of lenses.

> Which is why it’s unlikely that people who understand these issues will “stop using Haskell”

Plenty of people who value being able to analyse program and do proof don't use Haskell. The heart of the debate is "Is being pure worth the cost?".

Re: Functional languages should be so much better at mutation than they are

#135
post #107
post #40

Earlier quoted context omitted.

Can you provide evidence that code which is "as performant as using mutation" is generated? Mutation tends to be very hard to beat.

It's literally impossible on a CPU. Some people claim FP languages can make optimisations that are based on the fact that values are immutable and which other languages can't, and that's definitely true. But the problem is that those optimisations are almost never actually made by real programming languages, and when they are, they're still slower than a low level imperative language like C or Rust in very nearly eve…

No one needs to prove you wrong because that's not where the goal post actually is.

You could craft hand written assembly code which will be faster than optimised C code most of the time yet you don't. Plenty of programmers are perfectly writing imperative code in Java doing a ton of necessary boxing and unboxing. It's all a trade off between performance and usability. The fact is that the Ocaml compiler does a good enough job with functional code that its performance is actually comparable to imperative solutions most of the time.

Re: Functional languages should be so much better at mutation than they are

#136
There is a way to do FBIP without reference counting - use immutable store semantics (always copy). At that point you are doing a lot of copying but Haskell etc. are actually pretty good at managing this sort of profligate duplication. And of course it is possible to use RC-at-compile-time and other analyses to optimize away the copying - the difference is that runtime RC is not required like it is in Koka. There is even a static analysis algorithm from 1985 https://dl.acm.org/doi/abs/10.1145/318593.318660 (never implemented in Haskell because they went with the ST monad) There is a theorem in the paper that for "natural" translations of imperative programs into FP, their algorithm will optimize the FP back to the imperative program or better.

Re: Functional languages should be so much better at mutation than they are

#137
post #107
post #40

Earlier quoted context omitted.

Can you provide evidence that code which is "as performant as using mutation" is generated? Mutation tends to be very hard to beat.

It's literally impossible on a CPU. Some people claim FP languages can make optimisations that are based on the fact that values are immutable and which other languages can't, and that's definitely true. But the problem is that those optimisations are almost never actually made by real programming languages, and when they are, they're still slower than a low level imperative language like C or Rust in very nearly eve…

If you compile your immutable program with LLVM, literally one of the cure steps is transforming it into functional form that does not allow mutations.

This is called Single Static Assignment form and its denial of mutation is crucial to optimization, from common expression removal, to efficient register allocation, and all sorts of control flow analysis.

Re: Functional languages should be so much better at mutation than they are

#138
post #117

Earlier quoted context omitted.

By simulating exceptions, do you mean a `Result t e` type (which Haskell calls `Either l r`)? You can use these and the Functor/Applicative/Monad hierarchy to handle errors. What is presumably talked about is that Haskell also has actual exceptions, generated by calling e.g. `error` or `undefined`. The semantics of these are.. interesting, mostly thanks to lazy evaluation. For example, `fst (5, error "second") ` is s…

> By simulating exceptions, do you mean a `Result t e` type (which Haskell calls `Either l r`)? Yes, exactly. > The semantics of these are.. interesting, mostly thanks to lazy evaluation. For example, `fst (5, error "second") ` is safe to evaluate because the second half of the tuple is a thunk and does not get evaluated Correct, and the semantics of loops is also.. interesting. For example `fst (5, last [1..])` is a…

Hm yeah, I'm not sure what astrange's point was, other than probably dissatisfaction with the combination of exceptions and Either (which I think is awfully named, as it implies a certain 'equality' between l and r).

I haven't used Bluefin, but don't Bluefin exceptions suffer from the same issue where it, essentially, 'infects' the program flow? For example, `fst (5, error "second")` seems like it would translate to `fst $ (5,) throw e "second"`, where you would also need to pull an `e` from somewhere. More realistic, something like head would probably be quite awkward:

head e [] = throw e "head: empty list" head e (x:xs) = pure x

You now need to pass in the exception handle, and the return value is now `Eff es a` instead of `a`. This means that you cannot just use the result, so you will likely need to fill your program with monadic stuff like do-notation, and , complicating the program flow and likely also reducing laziness.

Re: Functional languages should be so much better at mutation than they are

#139
post #88

Earlier quoted context omitted.

Almost all GCs used in practice today only scan the set of live objects, which in normal operation is much smaller than the entire heap. They also allow much more efficient allocation and de-allocation. The problems with GC are threefold, and why you might not want it in a systems language: 1. GC requires more memory than strictly necessary to be efficient (usually about 1.5x - 2x the amount you absolutely need). You…

> You're basically trading runtime efficiency for memory. What do you mean? Aren't GCs both less efficient at run time and use more memory?

It depends what you mean by “efficient”: a world that controls when someone can free memory can be surprisingly efficient at dealing with the fundamental fragmentation problem in terms of overall churn over time (throughout) at the cost of space and immediate time (latency). Both are different forms of efficiency.

Manual memory management as a solution to the fragmentation problem trades that off, not knowing anything about when free might be called, and so has to lean towards optimising space and immediate time rather than throughout. But there’s still a memory manager behind the scenes that has to deal with fragmentation as well; there’s no get out of jail free card for that, and that complexity is still hidden.

(Helpful memory usage disciplines like arenas/pools have their desirable properties for the same reasons: it’s a discipline on when you free memory in order to avoid fragmentation.)

Re: Functional languages should be so much better at mutation than they are

#140
post #128

> A lot of people think that functional programming is mostly about avoiding mutation at all costs. People should try to stop thinking of mutation as something to be avoided, and start thinking of it as something to be managed. Mutating state is good. That's usually the whole point. What's bad is when you create "accidental state" that goes unmanaged or that requires an infeasible effort to maintain. What you want is…

This is a hill I will die on. Probably literally. If you are writing in a metaphor of equations, than yes, mutation is almost certainly going to bite you. If you are writing in a metaphor of process, you almost certainly want to manage, as you say.

I feel that early texts were good at this. Turtle Geometry is my personal favorite book in this vein. I seem to recall we spent a long time going over how to double buffer graphics so that you could be working on one buffer while letting the system draw the other. Not sure what texts we used for that, back in the day.

Later texts, though, go through a lot of hurdles to hide the fact that things are actively changing. The entire point is to change things.

Post reply on HN