4 ms·
> Using long sequences of poorly-labeled, nested arrow function returns is great fun until you have the task of deciphering someone else's. Something like that
by sullyj3 5y ago
> Using long sequences of poorly-labeled, nested arrow function returns is great fun until you have the task of deciphering someone else's.
Something like that would be considered bad Haskell code, yes. Haskell is designed from the ground up to support the functional paradigm. When people try to use functional style in languages that were designed with primarily procedural style in mind, the result is often ugly and difficult to follow. You just don't have the same issue in a language that's designed from the beginning as a functional language.
Something that people tend to miss is that you can write code that very much looks like a lot of procedural code in haskell:
let
x = 1
y = x + 5
z = 10 + y + z
in x + y + z
You can have bindings, just like you might use variables in a (eg) python function. The only difference is that the bindings are immutable. That turns out to not be as restrictive as you might expect - a lot of good python code only assigns to a given variable once.
I think it's a fair criticism to say that Haskell code can become opaque when it relies on more advanced language features and esoteric GHC extensions. The solution to this is to be disciplined and selective as a team about choosing which features you believe are worth their complexity/onboarding cost, and sticking to those choices.
Conversely, I find Haskell code that doesn't use those extra features to be much easier to understand than equivalent code in other languages, due to the extra guarantees I have about the code. For instance, I know that variables won't be mutated out from under me, things can't be null where they shouldn't be, and there are plenty of other assorted guarantees that come from having access to an expressive type system.
- mpoteat 5y agoPerhaps this is pedantic, but that doesn't look like good procedural code to me. Instead, it looks like a set of mathematical equations. I think there is intrinsic value in simple, procedural code that has state and produces side effects - it can even be typed! However, I think FP maximalism is bad for code readability. How might you write to a MongoDB document in Haskell, for example? A common example in this space is how to specify a baking recipe. Do you list it as a series of steps to perform on the world, or do you reductively assert what a cake is from base principles? I think Haskell developers need to realize that pure functional programming is intrinsically more difficult than other kinds. It requires a much higher ceiling for abstract thought. What I'm essentially trying to assert is that you have to be smarter than average (whatever that means) to read and write Haskell code. I believe this accounts for the majority of the perceived efficiency. The cost is that you are excluding people who are not mathematically talented.
- sullyj3 5y agoIt's not supposed to be good procedural code, it's supposed to be illustrative of the fact that a lot of code which people are used to seeing in procedural languages, which only involves assigning to a variable once, can be translated into a pure haskell function very straightforwardly, and it doesn't look intimidatingly esoteric like many people seem to expect. I can just as easily do it with strings if you're concerned about it being mathematical. I agree that there are many problems more naturally represented by procedural code, and as such it's important for every language, even functional languages, to have good constructs for representing a series of steps. Luckily, Haskell has such a construct in do notation. It looks like this: main = do putStrLn "What's your name" name <- getLine putStrLn ("Hello, " ++ name) I'm not familiar with MongoDB, but I found a haskell library for that and the example looks relatively straightforward to me, modulo possibly some unfamiliar syntax. It's a bit long, but it's doing more than just an insert. [1] I've heard the cake argument many times, and I agree that it's more naturally modelled as a series of steps. But I find it frustrating, because I've never heard a convincing argument for why the fact that one particular problem is more intuitively modelled as a sequence of steps, means all problems are. For example, imagine if you were never allowed to declaratively specify a DOM again using HTML, but instead you had to construct it as a series of calls to element.appendChild(). Would that really make your life easier? There are many problems for which a declarative description, not a procedure, is much more straightforward to understand. Another point is that you can also think of applying functions in succession ("function composition") as a series of steps! I find this pretty intuitive. For example, here's a function which takes a list of words and shouts them. The steps are: First concatenate the words together, then capitalize the resulting string, then append an exclamation mark: λ » shoutWords = unwords .> capitalize .> exclaim λ » shoutWords ["i'm", "shouting"] "I'M SHOUTING!" I think you're right about needing to have a certain level of smarts to get Haskell, but I think this is a consequence of some more advanced Haskell features (Typeclasses + higher kinded polymorphism), rather than the functional paradigm itself. For example, I think Elm is probably very approachable for people with a wide variety of different levels of mathematical ability. I think it's very easy to assume that functional programming is inherently more difficult, when it might well be that all that's going on is that people are more used to procedural programming because that's what they were taught first. I really would encourage anyone who thinks FP is inherently difficult to have a crack at learning Elm. [1] https://hackage.haskell.org/package/mongoDB-2.7.1.1/docs/Database-MongoDB.html https://hackage.haskell.org/package/mongoDB-2.7.1.1/docs/Dat...