Live data from Hacker News

Concurrency in Haskell: Fast, Simple, Correct

bitbashing.io

91–100 of 129 posts

Re: Concurrency in Haskell: Fast, Simple, Correct

#91
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…

STM happens inside the STM monad while regular effects happen in the ZIO monad. If you try to do ZIO effects inside an STM transaction you'll get a type error.

Scala doesn't enforce purity like Haskell though so it wont stop you if you call some normal Scala or Java code with side effects. In practice its not a problem because you're wrapping any effectful outside APIs before introducing them into your code.

Re: Concurrency in Haskell: Fast, Simple, Correct

#92

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

The author is thinking of updating the book to a second edition as well. Looking forward to it

noice

Re: Concurrency in Haskell: Fast, Simple, Correct

#93
post #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 popul…

Agreed completely. Most auto-vectorization approaches are hit-miss and you still cannot have big-binaries, where instruction set is decided dynamically, trivially.

ISPC comes close, but does come with a learning curve.

Re: Concurrency in Haskell: Fast, Simple, Correct

#94
post #49

Earlier quoted context omitted.

No one wants to be a python programmer. It's a practical language to get things done. It isn't a language to make you feel proud of yourself nor about the current state of our industry.

I’ve enjoyed making it go faster by finding quirks, but at this point it’s mostly become “OK, what else can I offload to C?” I should really learn Rust. Or Zig. I tried Nim (best of both worlds, Python-esque code that compiles to C!), but it wasn’t nearly as fast as my Python + C for my specific use case.

What exactly do you write, where your Python+C is faster than Nim which compiles to optimized C?

Re: Concurrency in Haskell: Fast, Simple, Correct

#95
From the footnotes:

> In bare-metal embedded systems or inside the operating system, it’s not unusual to manually break computation into state machines, driven by interrupts.

Although not the topic of TFA, in fact, the footnotes that this is "a whole different ball game." Does anyone have any good source for this aspect of 'low-level'/OS development? I'm more than capable of chasing down sources from a more high level introduction or overview, so anything would be helpful. This concept seems like it may just be a more pragmatic description of embedded/OS development than what I've read previously.

Re: Concurrency in Haskell: Fast, Simple, Correct

#96

Earlier quoted context omitted.

I’ve enjoyed making it go faster by finding quirks, but at this point it’s mostly become “OK, what else can I offload to C?” I should really learn Rust. Or Zig. I tried Nim (best of both worlds, Python-esque code that compiles to C!), but it wasn’t nearly as fast as my Python + C for my specific use case.

What exactly do you write, where your Python+C is faster than Nim which compiles to optimized C?

Generating millions of rows of synthetic data for testing RDBMS.

Tbf, I didn't spend much time trying to optimize the Nim code once I got a working PoC, so it's entirely possible that I could've made it faster.

Re: Concurrency in Haskell: Fast, Simple, Correct

#97

Earlier quoted context omitted.

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…

Clojure atoms use STM, though. I've been writing Clojure for almost a decade now, it's not that STM isn't great, it's just that immutable data will carry you a very long way - you just don't need coordinated mutation except in very narrow circumstances. In those circumstances STM is great! I have no complaints. But it just doesn't come up very often.

Re: Concurrency in Haskell: Fast, Simple, Correct

#98
post #97

Earlier quoted context omitted.

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…

Clojure atoms use STM, though. I've been writing Clojure for almost a decade now, it's not that STM isn't great, it's just that immutable data will carry you a very long way - you just don't need coordinated mutation except in very narrow circumstances. In those circumstances STM is great! I have no complaints. But it just doesn't come up very often.

I would say to the contrary it would come up all the time if the right idioms were in place.

For example, when it comes to concurrent access to a map the Clojure community generally forces a dichotomy, either stick a standard Clojure map in an atom and get fully atomic semantics at the expense of serial write performance or use a Java ConcurrentMap at the expense of inter-key atomicity (or do a more gnarly atom around a map itself containing atoms which gets quite messy quite fast).

Such a stark tradeoff doesn't need to exist! In theory STM gives you exactly the granularity you need where you can access the keys that you need atomicity for and only those keys together while allowing concurrent writes to anything else that doesn't touch those keys (this is exactly how e.g. the stm-containers library for Haskell works that's linked elsewhere).

Re: Concurrency in Haskell: Fast, Simple, Correct

#99
post #52

Earlier quoted context omitted.

Isn't concurrency in Rust a notorious pain point? Or am I confusing it with async which is different? [I am stuck in an era before parallelism, so I don't really understand these things]

This why I haven't fully embraced Rust yet. Whenever I ask about safely mutating shared state (see sibling comment), I'm met with silence, or some comment like: Rust guarantees that you aren't mutating shared state.

I'm surprised you say this. The core type system guarantees is that there is no aliasing while mutating, and no mutation while it is aliased. You get single writer multiple reader for free without overhead.

If you want multiple writers, you can always use the Arc container and use the built-in lock.

Re: Concurrency in Haskell: Fast, Simple, Correct

#100
post #3

In another life I will be a Haskell programmer

There's no time like the present. Feel free to reach out if I can help you along your journey

Not the person you're replying to, but I'll bite:

I've written low thousands of lines of Haskell. Similar to mikojan, I love Haskell in theory, but ended up not enjoying it as much in practice.

1. The multitude of string-y types. I end up converting between String, Text, Lazy Text, ByteString, Lazy ByteString, and I forget what else. Each library wants me to pass in a specific string type, and each other library returns a different string type. LLMs are good at this, also for a while I had a ton of helper functions to convert between any two string types. Still, perhaps there's a better way?

2. The error messages. I come from Elm, so I'm spoiled. Yes, I understand a language with HKTs will never have as nice error messages. Yes, LLMs are pretty good at explaining GHC error messages.

3. The stdlib. Haskell gets a lot of credit for safety, but a `head` blows up instead of returning a `Maybe`. I know there are other - safer - preludes, but I don't know how to choose between them. I don't know how using a different prelude would impact my projects.

I feel like my next step is either towards Idris, with its polished standard library (and dependent types baked into the language!), or towards something simpler and more Elm-like (Gleam perhaps, or Roc). But if you can sell me on Haskell, I'm all ears!

Post reply on HN