| > Haskell assumes an "open world" - i.e. everybody can add instances to a data type even after it has been defined already. TypeScript, which is my current OO language, will use signatures to match to an interface, so it's even more open: You can create an object with the right members and pass it in to a function expecting an interface without even explicitly identifying it as "implementing" the interface. > If anything, I've never seen a big OO program made out of truly reusable components. Agreed. The point of using OO in a giant complex program isn't just the reuse, which you point out is exaggerated. The point of using OO in a giant complex program is the isolation you get, so that a team of 1000 people can develop the app in a reasonable way. I think the cost of FP as the complexity of a program goes up is that the cognitive load to think about the structure of the program goes up exponentially faster than OO. Debugging is a huge issue when things get complicated, and the last I heard Haskell debugging is still in its infancy. A debugger where you just can step through the code is really, really important for some kinds of analysis. It's all Turing Complete, so you can do anything in FP that you can do in OO. It just feels harder to decompose problems into FP units than OO units, at least at a larger architectural level. Not everything is easily isolated: Sometimes you need a control over here to poke into the state of a control over there, and you don't want that information in some "god object" at the top level; you want a direct connection and mutability. I have heard good things about Elm, and will probably give it a try at some point. But my 30+ years of programming experience have given me a (possibly incorrect) strong intuition that FP just won't work well for some problems. Can they apply to them? Sure. > [...] pure FP, is especially well suited for complex problems. Which is why it's so popular for solving complex problems? Looking at a list of Haskell's uses in industry [1] and applications [2] I don't see a single example of Haskell used in what I would call a "complex problem". Lots of machine learning, parsing/compiling, and transformation tools. Some games written by amateur game developers -- getting a game working is about 10% of the problem. A very few more complex apps that I've never heard of, but nothing that hits the complexity of even a Microsoft Word or Adobe Photoshop, much less a 3d editor like Maya. There's an order of magnitude more complexity in an app like those. Haskell is 27 years old. Over the last ten years it's been incredibly popular. Totally enough time for at least a few high profile applications to have been created. Where are they? Maybe Haskell would be a better platform, but it's just harder for many programmers to think pure-FP. But even that's a real limitation: If you're putting more cognitive load on the developer, then you're just changing the problems, not preventing them. [1] https://wiki.haskell.org/Haskell_in_industry [2] https://wiki.haskell.org/Libraries_and_tools |
Row polymorphism is indeed very useful. Purescript (a Haskell descendant compiling to js) has it and I wish Haskell did too.
> The point of using OO in a giant complex program is the isolation you get, so that a team of 1000 people can develop the app in a reasonable way.
> Not everything is easily isolated: Sometimes you need a control over here to poke into the state of a control over there, and you don't want that information in some "god object" at the top level; you want a direct connection and mutability.
The above two statements directly contradict each other. Yes, OOP preaches isolation and programming against abstract interfaces, in theory. In practice, more often than not one is tempted to do something the easy way and "poke into the state" of another object. This has disastrous consequences: you never know what will happen where when you call a method. Everything is fair game. It's like changing the lock of the basement door in a skyscraper somewhere only to have it fall because the steal beams depended on this exact lock to hold some state, since it was "faster that way". It's insane.
I've seen so many OOP clusterfucks that I seriously can't believe that you haven't in your much longer career.
Sometimes FP is not a good idea - mostly when performance, memory or deterministic runtime behaviour is a must. But even there languages like Rust show that it may be possible to have one's cake and eat it too.
Other than that, I'd be genuinely interested in hearing what kind of problems you think FP wouldn't work well for.
> Which is why it's so popular for solving complex problems?
It is, actually. I've worked on a very complex codebase in Haskell at my last job (a pathfinding and ticket price calculation backend with ridiculous specifications full of special cases and exceptions that changed almost every day) and I was able to be productive almost from day one. We could refactor with almost absolute confidence because the language is pure and type safe, and we had to because the specs changed so quickly.
Facebook's spam filter and Jane Street's OCaml stack come to mind as other examples.
There aren't as many applications written in FP languages simply because these languages aren't that popular. But popularity isn't a metric of quality.
> If you're putting more cognitive load on the developer, then you're just changing the problems, not preventing them.
I absolutely find the opposite to be the case. Haskell reduces the cognitive load on the programmer, because it is pure (i.e. no need to keeping track of dozens of interactions at once) and type safe (i.e. a function marked as pure can't call a function with IO).
Not to mention things like an actual working software transactional memory implementation that makes concurrent programming as easy as writing a single threaded program. No other language, with the notable exception of maybe Clojure, has a practical STM library. But anyway, STM is just a bonus.
In short, I would say that FP actually delivers what OOP set out to but couldn't. Many FP ideas that were almost unheard of just a couple years ago, like immutable data, pure functions, composition over inheritance, non-nullable types, algebraic data types and so on are slowly but surely taking hold in the mainstream. Pure FP languages just take it to the next level :)