Live data from Hacker News

Concurrency in Haskell: Fast, Simple, Correct

bitbashing.io

81–90 of 129 posts

Re: Concurrency in Haskell: Fast, Simple, Correct

#81

https://www.oreilly.com/library/view/parallel-and-concurrent... is a great resource for those who want to go deeper into this

I read that book many years ago, but I haven't looked into Haskell for a long time. Is it still relevant today? I imagine many things have changed in 12 years!

The fundamentals are the same, and `async` is as relevant as it was back then. The ecosystem is extremely stable in that regard.

Re: Concurrency in Haskell: Fast, Simple, Correct

#82
post #39
post #12

Earlier quoted context omitted.

https://zio.dev/reference/stm/

> Implication of Using STM Running I/O Inside STM— There is a strict boundary between the STM world and the ZIO world. This boundary propagates even deeper because we are not allowed to execute arbitrary effects in the STM universe. Performing side effects and I/O operations inside a transaction is problematic. In the STM the only effect that exists is the STM itself. We cannot print something or launch a missile ins…

I am not super familiar with it, great question - my guess would be its the latter! Does Haskell's provide protections?

Re: Concurrency in Haskell: Fast, Simple, Correct

#83

Earlier quoted context omitted.

Yes indeed, unless you use ropes or other specialised structures

Lists aren’t copied on prepend. Tries (like scala’s Vector) or trie maps (the core map types of Scala, Clojure and probably Haskell?) aren’t copied on updates. In fact, whether a data structure is an immutable or persistent data structure or merely an unmodifiable data structure (like Kotlin uses) is based on whether it requires full copies on most updates or not. In FP languages, immutable data structures aren’t “sp…

> whether a data structure is an immutable or persistent data structure or merely an unmodifiable data structure...

This hurt my brain. It seems that in some places (e.g. Java land) unmodifiable refers to something that you can't modify but could just be a wrapper around a structure that can be modified. In that case they use immutable to mean something that is nowhere modifiable.

I may be misrepresenting this idea, but I think the terminology is so poor that it deserves to be misunderstood.

Re: Concurrency in Haskell: Fast, Simple, Correct

#84

I don't know how async is in other languages but I find Pythons async incredibly difficult to use, and I kinda feel validated about how poor chatGPT is at it as well. Is it because it is just a very hard thing, or is it because its a synchronous language, with async bolted on? (I'm talking about a purely language point of view, not from a python VM / GIL point of view)

It's because ``asyncio`` is a dogwater library that's barely functional and full of footguns. The ecosystem is about the same quality too.

Indeed, as much as I dislike async in general, asyncio is its own special hell.

Re: Concurrency in Haskell: Fast, Simple, Correct

#85
> 1. Compose the program into several threads of execution, traditionally scheduled and ran by the operating system

The step 0 is missing:

Compose the program into several lanes of execution, traditionally executed via SIMD.

This is a massive piece of performance left on the table on modern computer architectures, by assuming threading is the first manifestation of concurrency.

Re: Concurrency in Haskell: Fast, Simple, Correct

#86

My favourite thing about Haskell concurrency is that there are no colored functions [0]. Writing code in IO, or Async, or the next big thing (asychronous higher-order effect system of the future??), doesn't require language support like Python or Rust. The one construct that unlocks this lack of colored functions, STM, did require runtime support (as opposed to language support), which at least is transparent to down…

Coloured functions are a feature - not a bug, Haskell is full of them, and they are exactly what make STM safe in Haskell, but abandonware in other languages which have tried.

  2. The way you call a function depends on its color.
`>=` vs `=`

  3. You can only call a red function from within another red function.
This should sound pretty familiar! You can only call an IO function from within another IO function. STM in this case makes a third colour:

  IO can call IO functions.
  IO can call STM functions. (*)
  IO can call pure functions.

  STM can call STM functions.
  STM can call pure functions.

  pure functions can call pure functions.
(*) calling into an STM block from IO is what makes it 'happen for real': it's the `atomically` which has type STM a -> IO a.

Having these coloured functions is what made STM achievable back in the mid-late 2000s, since the mechanism to prevent STM or pure functions from calling IO was already in-place.

Other languages either tried to figure out how to contain the side-effects and gave up, or just released STM and put the onus on the user not to use side effects.

Re: Concurrency in Haskell: Fast, Simple, Correct

#87
post #83

Earlier quoted context omitted.

Lists aren’t copied on prepend. Tries (like scala’s Vector) or trie maps (the core map types of Scala, Clojure and probably Haskell?) aren’t copied on updates. In fact, whether a data structure is an immutable or persistent data structure or merely an unmodifiable data structure (like Kotlin uses) is based on whether it requires full copies on most updates or not. In FP languages, immutable data structures aren’t “sp…

> whether a data structure is an immutable or persistent data structure or merely an unmodifiable data structure... This hurt my brain. It seems that in some places (e.g. Java land) unmodifiable refers to something that you can't modify but could just be a wrapper around a structure that can be modified. In that case they use immutable to mean something that is nowhere modifiable. I may be misrepresenting this idea,…

Think about mutability in Java land this way:

  // Using mutability.
  // `increment` is void, and makes 2 bigger for everyone.
  increment(2); 

  // Typical Java "safety".
  // It's still void, but now it throws a RuntimeException
  // because the developers are saving you from making everyone's 2 bigger.
  increment(2);

  // Immutable
  // Returns 3
  increment(2);

Re: Concurrency in Haskell: Fast, Simple, Correct

#88

> 1. Compose the program into several threads of execution, traditionally scheduled and ran by the operating system The step 0 is missing: Compose the program into several lanes of execution, traditionally executed via SIMD. This is a massive piece of performance left on the table on modern computer architectures, by assuming threading is the first manifestation of concurrency.

SIMD has been somewhat of a massive failure in this regard. Unlike threads, most languages seem to ignore its existence and abdicate its usage to the sufficiently complex compiler.

I wish there was better author time feedback to the developer on where they're getting such a perf boost. As far as I'm aware there's no popular linting or blue squiggle to guide you in the right direction.

In games it seems like the popular pattern is to rewrite everything entirely in an entity component system framework.

Re: Concurrency in Haskell: Fast, Simple, Correct

#89

Earlier quoted context omitted.

I think Clojure has some kind of STM too? Haskell's STM is pretty world-class though. That's fair to say :)

Clojure's STM never really took off because, for various reasons, it's not as easy to compose as Haskell's (where you can build up a big library of STM blocks and piece them together at the very edges of your program). As such Clojure's STM implementation doesn't actually have a great reputation within the Clojure ecosystem where it isn't usually used in most production codebases (whereas in Haskell STM is often one…

My impression at least watching chatter over the last several years isn’t that it has a bad reputation but rather that people haven’t found a need for it, atoms are good enough for vast bulk of shared mutable state. Heck even Datomic, an actual bona fide database, doesn’t need STM it’s apparently all just an atom.

But I’ve never heard someone say it messed up in any way, that it was buggy or hard to use or failed to deliver on its promises.

Re: Concurrency in Haskell: Fast, Simple, Correct

#90
Correct? Anyone who has worked with concurrency in Haskell is probably laughing... :)

Haskell's IO type system doesn't model concurrency at all. `IO a` could be a fork and join, an infinite event loop, really anything, it's a black box in terms of "correctness". Better than using JavaScript maybe, but hardly "correct" in any sort of formal, tractable sense.

Post reply on HN