Isn't it the case that anything is very readable once you get the hang of it?
I think the problem is exactly in the "get the hang of it" part. For some languages, that's really difficult, while for others it's almost trivial. From my own experience, Haskell is very very difficult to "get the hang of" despite my multiple attempts, while something like Javascript is trivial for me (interestingly enough, except when it uses too much of the new FP patterns!) even when I do not program on it daily.
This is like complaining that Spanish is so hard to learn while English is actually quite intuitive. Of course it’s easier to understand what you already know.
Not at all. I tried to make the point of distinction clear by saying I do not use JS, nor Haskell, daily, but JS is more readable, without a doubt, so it's more like saying something like "english is more readable than french to a spanish speaker" (the analogy makes much less sense, but trying to correct yours). I think that we can agree that everyone's a priori is what they know in the world, which is common language... and everyone is familiar with "recipes", or step-by-step instructions... which is the same as imperative code, not functional.
Don't get me wrong, I like FP and have been trying to get into it for a long time. But currently I strongly believe FP as commonly done in Haskell is just too far from what we expect even before we start writing code. Combining functions and chaining Monads just seems to me to be extremely hard to do and understand, and I don't need to do any of that in "lesser" languages. However, I am finally "getting it" with newer languages like Flix and Unison - they let me just use `let` and stuff like that which makes the code trivial again, while being basically purely functional.
in JS would be: const strSum = str => str.split(' ').map(Number).reduce((a, b) => a + b, 0);
for a person who's not already a JS programmer, the first one would be more readable (without a doubt), it literally reads like plain English: "sum of mapped read of words".
Haskell's version is more "mathematical" and straightforward. Each function has one clear purpose. The composition operator clearly shows data transformation flow. No hidden behavior or type coercion surprises.
Whereas JS version requires knowledge of:
- How Number works as a function vs constructor
- Implicit type coercion rules
- Method chaining syntax
- reduce()'s callback syntax and initial value
- How split() handles edge cases
So while the JS code might look familiar, it actually requires more background knowledge and consideration of implementation details to fully understand its behavior. Javascript is far more complex language than most programmers realize. btw, I myself don't write Haskell, but deal with Javascript almost daily and I just can't agree that JS is "more readable" than many other PLs. With Typescript it gets even more "eye-hurting".
> in JS would be: const strSum = str => str.split(' ').map(Number).reduce((a, b) => a + b, 0);
It's funny to me that you quote the FP-like version of that in JS.
The more traditional version would be more like this:
function strSum(str) {
let words = str.split(' ');
let sum = 0;
for (word of words) {
sum += new Number(word);
}
return sum;
}
I do sincerely think this is more readable, no matter your background. It splits the steps more clearly. Doesn't require you to keep almost anything in your head as you read. It looks stupid, which is great! Anyone no matter how stupid can read this as long as they've had any programming experience, in any language. I would bet someone who only ever learned Haskell would understand this without ever seeing a procedural language before.
I don't even know where to start, your biases here are so explicit.
- The assumption that "verbose = readable" and "explicit loops = clearer"? Seriously?
- The suggestion that "looking stupid" is somehow a virtue in code? "Simple" I can still buy, but "stupid"... really?
- You're using new Number() - which is actually wrong - it creates a Number object, not a primitive;
- You `sum +=` is doing not a single op but multiple things implicitly: addition, assignment, potential type coercion, mutation of state;
- for loops are another layer of complexity - iterator protocol implementation, mutable loop counter management, scoping issues, potential off-by-one errors, break/continue possibilities, possible loop var shadowing, etc. Even though for..of is Javascript's attempt at a more FP-style iteration pattern and is safer than the indexed loop.
You clearly underestimate how natural functional concepts can be - composition is a fundamental concept we use daily (like "wash then dry" vs "first get a towel, then turn on water, then...").
Your "simple" imperative version actually requires understanding more concepts and implicit behaviors than the functional version! The irony is that while you're trying to argue for simplicity, you're choosing an approach with more hidden complexity.
Again, I'm not huge fan of Haskell, yet, the Haskell version has:
- No hidden operations
- No mutation
- Clear, single-purpose functions
- Explicit data flow
You have just demonstrated several key benefits of functional programming and why anyone who writes code should try learning languages like Haskell, Clojure, Elixir, etc., even though practical benefits may not be obvious at first.
I spent years writing JavaScript, PHP, and Ruby. I thought Haskell was weird and hard, and probably not practical in the real world.
As it turned out, I was just being a fool. Once you actually learn it, you realise how silly the opinions are that you had of it before you learned it.
Advent of Code is running right now. Why don't you just try learning the language?
I learned the language more than 10 years ago. No, it's not for me. Please don't assume that because somebody doesn't find Haskell readable the person must be ignorant.
Maybe „French is more readable than Korean” would be a better analogy. Sure, if you’re already familiar with the Latin alphabet, but Hangul is clearly a better writing system.
> I do not use JS, nor Haskell, daily, but JS is more readable
I’m guessing you do use languages that are very similar to JS. Like a Spanish speaker saying “I don’t speak Italian or Chinese but Italian is way easier.” If you wrote F# every day you would probably find Haskell syntax quite intuitive
I was trying to make the point that no, it's not that at all. But I guess it's a very hard point to make and even though I am convinced that I'm right and this has nothing to do with familiarity, I can't find any serious research showing either way.
I know a dozen languages well. Everyone here thinking it's just ignorance, but that's not the case. There's just no way that, for me, Haskell and similar languages are readable in any sense just because they're more concise. If that was the case Haskell still wouldn't be close to the most readable, but something like APL or Forth would.
I've tried for more than 10 years to be like you guys and read a bunch of function compositions without any variable names to be seen, a few monadic operators and think "wow so easy to read"... but no, it's still completely unreadable to me. I guess I am much more a Go person than a Haskell person, and I am happy about that.
It is a point of familiarity. Just because you've been coding in multiple languages before doesn't necessarily make you "a better programmer" (in the sense that you've developed good instincts to quickly mentally parse different pieces of code) - you could have been using programming languages of similar paradigms. It took me a few months of writing Clojure (niche language) to start seeing things in a different light - I also, just like you, used to think that imperative constructs are more readable and easier to reason about. I was wrong.
There's no such thing as a "Go person" or a "Haskell person"; all programming languages are made up. Nobody has "more natural inclination" for coding one way than another. Just get your ass out of the comfort zone, try learning a new (to you) language - give it a heartfelt attempt to use it - that may change your life.
Just to be clear - I'm not saying Haskell is easy, oh no, not at all. I'm just saying that it stops being so intimidating and weird after a while.
> and everyone is familiar with "recipes", or step-by-step instructions... which is the same as imperative code, not functional.
everyone is familiar with "I don't know how exactly, but generally it would be this way..., we can discuss specifics later" which is the same as reading the above pointfree notation (sum . map read . words) verbatim instead of imperatively inside-out: something is a sum of all parsed values of space-separated words.