News for hackers. Stuff that matters.
Re:8 months of OCaml after 8 years of Haskell in production ... by aidenn0 on Monday December 02, 2024 @10:27PM (#42302834)
Firstly, this doesn't mention the thing that bothered me the most in my few encounters; how baroque and fluid the tooling is.

I have regularly run into code that can only be compiled by a rather narrow range of ghc versions; too old or too new and it just won't.

> Haskell probably has the most elegant syntax across all languages I’ve seen (maybe Idris is better because dependently typed code can become ugly in Haskell really quickly).

I have a general dislike for ML-type syntaxes, and Haskell is my least favorite of the ML-type syntaxes I have encountered. Presumably there is some underlying set of principles that the author would like maximized that I assuredly do not.

> There’s utter joy in expressing your ideas by typing as few characters as possible.

Disagree; if I did agree, then I would probably use something from the APL family or maybe Factor.

Re:8 months of OCaml after 8 years of Haskell in production ... by yoyohello13 on Monday December 02, 2024 @11:29PM (#42303075)
That’s funny. I actually love Haskell syntax, it’s by far my favorite language to look at.
Re:8 months of OCaml after 8 years of Haskell in production ... by gooosle on Tuesday December 03, 2024 @12:09AM (#42303221)
People often say that before they realize how complex and messy real-world Haskell looks like. The indentation-based rules aren't even defined anywhere except via imperative code in the implementation.
Re:8 months of OCaml after 8 years of Haskell in production ... by brabel on Tuesday December 03, 2024 @02:06AM (#42303662)
If that's true, that's such a disappointment. I always thought of Haskell as the pinnacle of mathematical discipline in programming (though too hard for me to wrap my head around!).
Re:8 months of OCaml after 8 years of Haskell in production ... by mjan22640 on Tuesday December 03, 2024 @03:28AM (#42304095)
Such a pinnacle would be Agda. Haskell has mathematical holes.
Re:8 months of OCaml after 8 years of Haskell in production ... by johnnyjeans on Tuesday December 03, 2024 @01:25PM (#42309416)
Haskell is 30 years old at this point. It was pretty cutting edge in the 90s, but the pinnacle has climbed ever higher.
Re:8 months of OCaml after 8 years of Haskell in production ... by worksonmymach on Tuesday December 03, 2024 @02:17AM (#42303715)
Oh sir we call that "operational semantics"
Re:8 months of OCaml after 8 years of Haskell in production ... by yazzku on Tuesday December 03, 2024 @09:25PM (#42313949)
You have earned your Martini.
Re:8 months of OCaml after 8 years of Haskell in production ... by _flux on Tuesday December 03, 2024 @02:57AM (#42303915)
Hmm, isn't this the definition? 10.3 of https://www.haskell.org/onlinereport/haskell2010/haskellch10...

> The effect of layout is specified in this section by describing how to add braces and semicolons to a laid-out program.

I wasn't going to actually read that in detail to see if it makes any sense, though, but it looks very detailed :).

Re:8 months of OCaml after 8 years of Haskell in production ... by pyrale on Tuesday December 03, 2024 @03:17AM (#42304029)
Nothing forces it to be messy. A well-tended haskell codebase is great. On the oposite, I would say that a poor haskell codebase is painful, but far from being as painful as a poor java/js codebase.

Anecdotally, in my years of haskell at separate places, I had to debug/repl maybe had to repl once or twice. I wish I could say that of mycurrent java gig.

Re:8 months of OCaml after 8 years of Haskell in production ... by tome on Tuesday December 03, 2024 @07:06AM (#42305286)
My experience is similar, and in addition I would say that I have come across badly written, difficult to understand Haskell code, but it was always straightforward to refactor it into something clearly written.
Re:8 months of OCaml after 8 years of Haskell in production ... by elbear on Tuesday December 03, 2024 @03:20AM (#42304048)
I've written Haskell code in production and I still find the syntax the most eloquent. And you don't have to know the indentation rules, you just pick them up from usage. Just like you don't have to know the grammar rules.
Re:8 months of OCaml after 8 years of Haskell in production ... by johnnyjeans on Tuesday December 03, 2024 @01:30PM (#42309494)
That's because real-world Haskell tends to not be idiomatic, and it involves a lot of directly telling GHC what to do. Mathematicians don't have to (and rarely, if ever) make efficient code. GHC is a really advanced and impressive compiler, but that really doesn't amount to much. At some point the language just devolves into understanding what arcane compiler internals you need to invoke, and it's more like a bunch of C macros with a fancy runtime.
Re:8 months of OCaml after 8 years of Haskell in production ... by yoyohello13 on Tuesday December 03, 2024 @04:34PM (#42311787)
Maybe it's because I code Python professionally, or because I use an autoformatter (ormolu) for Haskell, but I have literally never had an issue with the indentation rules.
Re:8 months of OCaml after 8 years of Haskell in production ... by bmitc on Monday December 02, 2024 @11:05PM (#42302995)
That's interesting you dislike ML syntaxes when they're generally thought to be the cleanest syntaxes. What syntax families do you generally like?

Also, Haskell isn't really ML-syntax. I love MLs but find Haskell syntax pretty ugly.

Re:8 months of OCaml after 8 years of Haskell in production ... by The_Colonel on Monday December 02, 2024 @11:30PM (#42303082)
> when they're generally thought to be the cleanest syntaxes

That might be true for academics. But most engineers don't consider ML syntax to be the cleanest, since most don't know any ML language.

Re:8 months of OCaml after 8 years of Haskell in production ... by bmitc on Monday December 02, 2024 @11:44PM (#42303125)
MLs aren't really academic languages aside from Standard ML. F# and OCaml are very pragmatic languages. The cleaner parts of Rust came from ML.

What syntaxes do engineers find clean? I don't understand the distinction you're making.

Re:8 months of OCaml after 8 years of Haskell in production ... by t-writescode on Tuesday December 03, 2024 @12:52AM (#42303343)
I assume they mean:

  * Python, Ruby, C#, Java, Go-style languages?
I imagine most developers operate in neither ML languages nor Lisp-style languages.

The most advanced "FP" trick that I imagine most developers use is Fluent-style programming with a whole bunch of their language's equivalent of:

  variable
    .map do ... end
    .map do ... end
    .flatten
Addendum: or maybe Linq in C# Addendum 2:

And even the fluent-style trick in those languages tends to follow a similar pattern. Using Kotlin and Ruby as examples, since those are my (edit: main) languages,

  variable
    .map do |i| something_with(i) end
    .map { |i| something_else(i) }
    .flatten
shows familiar tricks. The dot operator implies that the thing previous to it has an action being done; and curly braces or the "do" operation both imply a block of some sort, and so a quick glance is easy to follow.

In Kotlin, this gets a little bit more confusing (yes, really) because it's common to see:

  variable
    .map { somethingWith(it) }
    .map { somethingElse(it) }
    .flatten()
And now there's this magic "it" variable, but that's easy enough to guess from, especially with syntax highlighting.

Anything more advanced than that and the cognitive load for these language starts to rise for people that aren't deep in them.

When you're starting working with a new language, that does increase difficulty and may even be so much of a barrier that developers may not want to hop over.

Re:8 months of OCaml after 8 years of Haskell in production ... by skydhash on Tuesday December 03, 2024 @10:48AM (#42307429)
When you start working in a new language, the best thing to do is to get a book and familiarize yourself with any constructs or patterns you are not familiar with. Expecting things to be similar to what you’re used to (which lower the learning curve) is a fool’s errand.
Re:8 months of OCaml after 8 years of Haskell in production ... by t-writescode on Tuesday December 03, 2024 @02:21PM (#42310124)
To learn a new language, you need a reason to learn that new language and you need sufficient drive to go through with it.

Having familiar constructs not only make it easier to code-switch between languages (people that work on multi-language projects know that pain pretty well), but also decreases the barrier to entry to the language in the first place.

Re:8 months of OCaml after 8 years of Haskell in production ... by wyager on Monday December 02, 2024 @11:33PM (#42303091)
> most engineers don't consider ML syntax to be the cleanest, since most don't know any ML language.

This is like saying "most uncontacted Amazonian tribes don't like Shakespeare, because they've never read it". Sure, but why would we care about their opinion on this topic?

Re:8 months of OCaml after 8 years of Haskell in production ... by unscaled on Tuesday December 03, 2024 @12:07AM (#42303211)
They might think Shakespeare's story are silly even if they did read it. In fact, there is at least one widely publicized instance where exactly the same thing happened with a culture that wasn't exposed to Shakespeare before:

https://law.ubalt.edu/downloads/law_downloads/IRC_Shakespear...

The same idea is probably true with programmers who have grown used to C-like syntax or even Python-like or Ruby-like syntax. Syntax is at least in great part a cultural thing and your "cultural background" can affect your judgement in many cases:

1. Are braces good? Some programmers find them noisy and distracting and prefer end keywords or significant whitespace, but other programmers like the regularity and simplicity of marking all code blocks with braces.

2. Should the syntax strive for terseness or verbosity? Or perhaps try to keep a middle ground? At one end of the spectrum, Java is extremely verbose, but a lot of Java engineers (who have generally been exposed to at least one less-verbose language) are perfectly OK with it. The trick is that the main way that code gets typed in Java used to be copy-paste or IDE code generation (and nowadays with LLMs typing verbose code is even easier) and reading and navigating the code is done with the help of an IDE, so a lot of the effects of having a verbose language are mitigated. Diffs are harder to review, but in the Enterprise app world, which is Java's bread and butter, code reviews are more of a rubber stamp (if they are done at all).

3. Lisp-like S-expression syntax is also highly controversial. Many people who are introduced with it hate it with passion, mostly because the most important syntax feature (the parentheses) is repeated so often that it can be hard to read, but advocates extol the amazing expressive power, where the same syntax can be use to express code and data and "a DSL" is basically just normal code.

Re:8 months of OCaml after 8 years of Haskell in production ... by johnisgood on Tuesday December 03, 2024 @04:03AM (#42304273)
I think Ada's verbosity is one of its strengths. Cannot say the same for Java, however.
Re:8 months of OCaml after 8 years of Haskell in production ... by naasking on Tuesday December 03, 2024 @09:06AM (#42306135)
There's "verbosity as descriptive clarity", and there's verbosity as in "I already said this, why do I have to repeat myself?" Ada unfortunately still has some of the latter, otherwise I would agree.
Re:8 months of OCaml after 8 years of Haskell in production ... by johnisgood on Tuesday December 03, 2024 @09:30AM (#42306407)
I mean, it is supposed to be verbose for descriptive clarity.
Re:8 months of OCaml after 8 years of Haskell in production ... by speed_spread on Tuesday December 03, 2024 @11:05AM (#42307653)
Java is really not that verbose if steer out of the 25+ years old conventions that were defined to justify expensive proprietary tooling. Leave all fields package scope or public final, so you don't need getters and setters. On JDK21+ use records and pattern matching. Go procedural + lambda, don't be afraid to use static methods. When OO is required, prefer composition over inheritance. Adopt a proper annotation processor library such as autovalue to eliminate remaining boilerplate.
Re:8 months of OCaml after 8 years of Haskell in production ... by aidenn0 on Tuesday December 03, 2024 @12:54AM (#42303351)
I love most entries in the Lisp family.

I find Python to be quite readable as well.

Re:8 months of OCaml after 8 years of Haskell in production ... by bmitc on Tuesday December 03, 2024 @12:58AM (#42303367)
If you like Python and Lisps, then I'm surprised you don't like F#. It is much more concise than Python, even for pure OOP programming.
Re:8 months of OCaml after 8 years of Haskell in production ... by IshKebab on Tuesday December 03, 2024 @02:49AM (#42303871)
I also dislike them. And I wouldn't disagree about them being "the cleanest", but cleanliness of syntax is only one concern. I also need to be able to mentally parse it, and on that from OCaml is very bad in my experience (haven't used Haskell much so I can't comment on that).

I've said this before but if you remove all punctuation and capitalisation from English it will make it look "cleaner", but it will also make it awful to read.

Look how "clean" text is if you get rid of all the spaces!

https://en.wikipedia.org/wiki/Scriptio_continua#/media/File%...

Clearly brilliant.

Re:8 months of OCaml after 8 years of Haskell in production ... by bmitc on Tuesday December 03, 2024 @11:24AM (#42307894)
The argument you make about literature is one I have made before, but I don't think it applies here. To me, languages with clean syntax aren't just removing things arbitrarily. They remove things that aren't needed or they otherwise have large amounts of consistency.

Let's look at three implementations of a doubling function in modern languages where at least two of them are considered "clean" syntaxes.

F#:

    let double x =
        2 * x
Python:

    def double(x: int) -> int:
        return 2 * x
Rust:

    fn double(x: i32) -> i32 {
        return 2 * x;
    }
Tying back to my original point, are the brackets, annotations, semicolons, and return really needed? From my perspective, the answer is no. These are the simplest functions you can have as well. The differences get multiplied over a large codebase.

Are people here really making the argument that F# and MLs don't have clean syntax? All three of these functions have the same IDE behavior in terms of types being showcased in the IDE and also in the type-checking processes, with F# and Rust's type-checking happening at the compiler level and Python's happening with MyPy. People might argue that I left off type annotations for F#, and that's true, but I did so because they aren't required for F# to compile and have the same IDE features like the other languages. Even if I did, it would look like:

F# with type annotations:

    let double (x: int) : int =
        2 * x
which is still cleaner.
Re:8 months of OCaml after 8 years of Haskell in production ... by steveklabnik on Tuesday December 03, 2024 @12:05PM (#42308430)
Idiomatic Rust would look like this:

    fn double(x: i32) -> i32 {
        2 * x
    }
The reason Rust requires types here is because global inference is computationally expensive and causes spooky action at a distance. The only real difference between your F# and this is the braces, which I do personally think makes code easier to read.

Of course there’s more overhead in smaller functions. I’d never write this code in Rust. I’d either inline it, or use a closure, which does allow for inference, and dropping the braces given that this is a one liner:

    |x| 2 * x
Different needs for different things.
Re:8 months of OCaml after 8 years of Haskell in production ... by itishappy on Tuesday December 03, 2024 @12:24PM (#42308638)

    #  Rust
    let double = |x| 2 * x;
    double(3);

    // F#
    let double = (*) 2
    double 3

    -- Haskell
    let double = (*2)       
    double 3

    #  Python
    double = lambda x: 2 * x
    double(3)
Re:8 months of OCaml after 8 years of Haskell in production ... by bmitc on Tuesday December 03, 2024 @01:22PM (#42309365)
If I am understanding that |x| 2 * x in Rust is an anonymous function, another F# equivalent is fun x -> 2 * x.
Re:8 months of OCaml after 8 years of Haskell in production ... by neonsunset on Tuesday December 03, 2024 @01:38PM (#42309596)
The Haskell and F# examples above use partial application.

This also works:

  let zeroCount = numbers |> Seq.filter ((=) 0) |> Seq.length
Re:8 months of OCaml after 8 years of Haskell in production ... by steveklabnik on Tuesday December 03, 2024 @06:21PM (#42312810)
It's a closure, not just an anonymous function, though it of course has an empty environment so it's not a significant difference in this case. Rust doesn't have syntax for anonymous functions, only closures.
Re:8 months of OCaml after 8 years of Haskell in production ... by bmitc on Tuesday December 03, 2024 @01:19PM (#42309337)
I thought that the Rust playground was requiring me to use return, but I was mistaken. However, it actually lends to my original point though because I would wager that dropping the return was part of the influence of ML on the beginnings of Rust.
Re:8 months of OCaml after 8 years of Haskell in production ... by steveklabnik on Tuesday December 03, 2024 @06:20PM (#42312804)
Expression orientation certainly comes from that general space, for sure.
Re:8 months of OCaml after 8 years of Haskell in production ... by IshKebab on Tuesday December 03, 2024 @02:14PM (#42310048)
> Tying back to my original point, are the brackets, annotations, semicolons, and return really needed? From my perspective, the answer is no. These are the simplest functions you can have as well. The differences get multiplied over a large codebase.

The answer is no for this trivial function. As your code goes beyond this it gets harder for humans to parse and so the syntax becomes more necessary.

My earlier analogy is pretty perfect here actually. Do you really need spaces in "thank you"? No clearly not. Does that mean you shouldn't use spaces at all?

> Are people here really making the argument that F# and MLs don't have clean syntax?

No. You are literally replying to a comment where I agreed that it is "clean".

Re:8 months of OCaml after 8 years of Haskell in production ... by jes5199 on Tuesday December 03, 2024 @12:29AM (#42303279)
I wrote Haskell for a couple years and I _never_ figured out the indentation rules. The haskell people seemed confused that it was even possible to find it confusing

and then there’s “do” notation. I has three people tell me “it’s just a simple mechanical transformation from lambdas” oh yeah? how? they couldn’t explain that either

Re:8 months of OCaml after 8 years of Haskell in production ... by solomonb on Tuesday December 03, 2024 @01:13AM (#42303426)

    mySubroutine = do
      foo <- mkFoo
      bar <- mkbar foo
      mkBaz bar
    
    mySubroutineV2 =
      mkFoo >>= \foo ->
        mkBar foo >>= \bar ->
          mkBaz bar
Re:8 months of OCaml after 8 years of Haskell in production ... by edflsafoiewq on Tuesday December 03, 2024 @01:48AM (#42303567)
Note that this is same desugaring for normal let

  let x = y in F   <===>   (\x.F)(y)
just replacing function application with a different function (>>=).
Re:8 months of OCaml after 8 years of Haskell in production ... by Athas on Tuesday December 03, 2024 @02:44AM (#42303838)
This is not the case in Haskell, because let-bindings can be self-referential, while lambdas cannot (without using a fixed point combinator). Also, in most functional languages, a let-binding causes type generalisation, which is not the case for a lambda.
Re:8 months of OCaml after 8 years of Haskell in production ... by chombier on Tuesday December 03, 2024 @02:47AM (#42303863)
Not exactly the same: `x` is given a polymorphic type (in F) in Haskell (restricted to values in ML) whereas the unannotated let-over-lambda will give `x`a monomorphic type.
Re:8 months of OCaml after 8 years of Haskell in production ... by solomonb on Tuesday December 03, 2024 @02:25AM (#42303752)
You can desugar let bindings that way but often times (as I believe is the case in GHC) you have a `Let` term in your AST.
Re:8 months of OCaml after 8 years of Haskell in production ... by pyrale on Tuesday December 03, 2024 @03:09AM (#42303974)
The reason people can’t remember it on the spot is that it’s really not necessary to understand how do-notation desugars in order to use it.

People usually check it once, see that it is correct and forget about it.

Re:8 months of OCaml after 8 years of Haskell in production ... by tikhonj on Tuesday December 03, 2024 @02:52AM (#42303895)
Do-notation is not all that different—if anything, it is simpler—than async/await syntax that's gotten popular in a bunch of mainstream languages. I don't know if that makes it easy or difficult in an absolute sense, but it isn't any worse than Python/JavaScript/etc.

The indentation rules are definitely a mess though :/

Re:8 months of OCaml after 8 years of Haskell in production ... by elbear on Tuesday December 03, 2024 @03:15AM (#42304015)
I wrote a tutorial about do notation. Maybe it helps https://elbear.com/a-user-guide-for-haskell-monads
Re:8 months of OCaml after 8 years of Haskell in production ... by Tainnor on Tuesday December 03, 2024 @12:39AM (#42303307)
I'll agree about the weird Haskell indentation rules.

But do notation really is just syntactic sugar for a chain of >> and >>= applications (plus "fail" for invalid pattern matches). It's not usually pretty or understandable to write it that way, but it's a very simple translation. If the people you talked to couldn't explain it to you, I think they maybe didn't understand it well themselves.

Re:8 months of OCaml after 8 years of Haskell in production ... by lmm on Tuesday December 03, 2024 @01:12AM (#42303421)
> and then there’s “do” notation. I has three people tell me “it’s just a simple mechanical transformation from lambdas” oh yeah? how? they couldn’t explain that either

Scala's for/yield (which is pretty similar) you can literally do an IDE action in IntelliJ to desugar it.

I forget the precise Haskell syntax, but do {a <- x; b <- y; c <- z; w } is sugar for something like x >>= $ \a y >>= $ \b z >>= $ \c w . Hopefully the pattern is clear. Were there cases where you actually couldn't see how to desugar something, or are you just nitpicking about them calling it a mechanical transformation without being to explain the precise rules?

Re:8 months of OCaml after 8 years of Haskell in production ... by worksonmymach on Tuesday December 03, 2024 @02:15AM (#42303700)
To understand "do" you need to understand the underlying >>= and return operators for your monad.

If you can use >>= and return to do it then "do" is indeed a mechanical transformation.

It is like await if you understand JS promises.

Re:8 months of OCaml after 8 years of Haskell in production ... by mrkeen on Tuesday December 03, 2024 @03:01AM (#42303931)
> I _never_ figured out the indentation rules

Weird. Haskell's my preferred language and I thought there was only one indentation rule - if something's further to the right it's part of the same expression, and if something's down it's a new expression.

  f
   x
    y
  g z
... With a slight addendum that you don't need to write 'let' on consecutive lines, e.g.

  let x = ...
      y = ...
Re:8 months of OCaml after 8 years of Haskell in production ... by yodsanklai on Tuesday December 03, 2024 @05:47AM (#42304858)
> I _never_ figured out the indentation rules

I'm glad I'm not the only one. The white-space as syntax in some cases is very confusing. It took me a while to figure it out.

Re:8 months of OCaml after 8 years of Haskell in production ... by pjmlp on Wednesday December 04, 2024 @05:01AM (#42316024)
It is the same as in any ML derived language, or Python.

I also don't see the issue, when there is tooling that complains about broken indentation.

Re:8 months of OCaml after 8 years of Haskell in production ... by bbminner on Tuesday December 03, 2024 @01:04AM (#42303391)
I agree. I have limited experience with FPs, and I can get a hang of what is happening in OCaml examples relatively easily, but Haskell examples feel more like something akin to Forth - if I really needed, I could parse it with my brain, but cryptic one liners like that feel more like "puzzles" than an actual useful program.
Re:8 months of OCaml after 8 years of Haskell in production ... by kqr on Tuesday December 03, 2024 @08:00AM (#42305635)
I feel like there's nuance here that a lot of people don't mention.

There are the actual puzzles that have been minified beyond recognition, and one has to work backwards to figure out what clearer code the author started from. I don't think anyone likes this code, but it gets written by people who are more used to writing code than reading it.

There is also the incredibly clear, straight-forward code that could have come from any other language. If you manage a sane production Haskell codebase, you'll have a lot of this.

In between those two, there is clear code but which you wouldn't find in any other language. This is code that uses well-known Haskell idioms that anyone who works with a lot of Haskell code will recognise, but which look like puzzles to someone who has not worked with a lot of Haskell. These are things like

    guard (age person >= 18) $> beer
to return Just beer to someone of age, but Nothing to someone underage;

    Uuid.fromWords <$> getRandom <*> getRandom <*> getRandom <*> getRandom
to return a randomly generated UUID;

    maybe (compute_fresh seed) pure cached_value
to use a cached value if it exists, computing it from scratch if it did not; or

    traverse_ $ \elem -> do
        error "stub"
to create a function that loops through a collection and executes a side effect for each element.

These look like nonsense to people not familiar with the idioms, but they appear frequently enough that they are no longer puzzles.

Re:8 months of OCaml after 8 years of Haskell in production ... by serbuvlad on Wednesday December 04, 2024 @02:34AM (#42315268)
Maybe this is a bit off-topic but I have to say: I don't _get_ FP languages. I get the idea of having functions with no side-effects. I think that's a great thing. But this can be achieved in every language.

Sure, the statements in the function will have side-effects on local variables, but as long as the function isn't too long, and you can comprehend all of it at a time, that's not a problem.

Your examples of "clean code" aren't any cleaner than what can be found in any imperative language.

Using C++ (with std::optional), for reasons of familiarity.

    (person.getAge() >= 18) ? "beer" : {};

    UUID::fromWords(getRandom(), getRandom(), getRandom(), getRandom());

    cache.has_value() ? cache : (cache = computeFresh(seed));

    for (auto& elem : collection) {
        modify(elem);
    }
Re:8 months of OCaml after 8 years of Haskell in production ... by Tainnor on Wednesday December 04, 2024 @07:41AM (#42316873)
Other languages can't help you track that a function that transitively calls 100 other functions is side-effect free, Haskell can.

> UUID::fromWords(getRandom(), getRandom(), getRandom(), getRandom())

This ignores that getRandom() is a side-effecting function (it has to be because it returns something different every time). And that's not just a "local variable". UUID.fromWords val1 val2 val3 val4 works in Haskell too, the "extra syntax" is to be able to all that in IO (i.e. with side effects). If you want it in a form that is more recognisable, you could write it as

  getUuid :: IO UUID
  getUuid = do
    val1 <- getRandom
    val2 <- getRandom
    val3 <- getRandom
    val4 <- getRandom
    return UUID.fromWords val1 val2 val3 val4
but that's unnecessarily verbose if you know the idiom.

Your cache example is similarly side effecting.

Re:8 months of OCaml after 8 years of Haskell in production ... by mark_l_watson on Tuesday December 03, 2024 @08:12AM (#42305701)
Compiler version issues are a pain. For most programming languages I use, I like to constantly update toolchain and library versions. I fight that tendency with Haskell. “cabal freeze” can be your friend.

I now find that using some combination of Claude, Gemini, and ChatGPT makes using Haskell more pleasant for processing compiler error and warning messages, suggesting changes to my cabal or stack configuration files, etc.

Re:8 months of OCaml after 8 years of Haskell in production ... by johnnyjeans on Tuesday December 03, 2024 @01:50PM (#42309739)
For me, my problem with Haskell's syntax is less rooted in the fact that it's in the ML-family. It's more to do with just how horrific complex type aliases can end up being thanks to currying. Imagine we have type aliases that are built up out of function signatures, made up of more aliases of function signatures, and this is a tower of some 20 layers deep. If you're working with types at different levels of this tower of garbage at the same time, you very quickly end up in an associativity hell and the type signatures you have to work with are beyond unhelpful.

Combination of both the flaws of currying as a concept, as well as the complexity of Haskell's type system.