Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

I learned Haskell and used it (and heavily functional Scala) professionally for about 6 years.

I feel learning Haskell was worthless. It did not teach me anything about decomposing problems into function units, compositional sequences, pure functions / immutable data structures, lazy evaluation or asynchronous programming that I have found useful in modeling solutions to software problems.

Guarantees from the compiler and use of the type system itself for type designs like phantom types and type class patterns did not help reduce behavioral bugs and the slower development cycle of waiting for compilation (instead of just using occasional unit test runs to check simple safety conditions in lighter weight dynamically typed languages) was a very significant cost.

It was no easier, and often much harder, to enable extensibility into systems designed in Haskell because the constraints of the extensible needs of the system were only ever learned from changing business circumstances after the fact and could not be reflected in anticipated up-front design, which is perhaps the number one need of business software yet is an area where functional languages are uniquely poorly suited even with veteran, highly experienced engineers on the team like we had.

In the end, following simple patterns of composition and function purity while avoiding cookie-cutter design patterns and avoiding use of object / class constructs is all you need. This is easy to achieve in many imperative languages while leaving much greater flexibility to choose mutation, treat safety as a resource to be traded off instead of enforced in all cases, etc.

“Module oriented programming” in Python or C, letting lightweight unit tests replace heavy reliance on type system patterns, just using simple structs / namedtuples / dataclasses that posses zero function logic, and creating imperative APIs around functional-inspired core implementations is strictly better.

Really, strong adherence to statically typed functional languages with lazy evaluation is a religious trap. Learning that it’s not all it’s cracked up to be early in your career is critical for success.



> yet is an area where functional languages are uniquely poorly suited

Can you clarify if you mean that the type system gets in the way here, or the same would apply to even dynamically typed functional languages?

I'm trying to understand if you think a static type system is the hindrance here, or the language being functional in paradigm.


Type system designs in statically typed functional languages are intended to represent increasingly abstract correctness constraints by transforming the business logic of the problem at hand into rules subject to the validation of the compiler.

This is quite different than object oriented or even compiled imperative languages where type system constructs contain data and function units that represent internalized constraints.

In functional programming you set up types and their constraints such that the business logic you require is a derivable consequence of the system and any other outcome is as close to provably impossible as can be. The less of this you choose to enforce, the more “imperativy” or “objecty” your use of that functional language is.

In imperative or OO languages you choose to make atomic units that have internal structure, but whose behavior across the interaction of the units is not itself a derivable consequence of any more abstract set of rules. Not even interfaces or templates represent this - they govern how components can communicate but do not limit what components can do.

You use the program’s structures to carry out the required business logic, but you cannot truly prove you haven’t allowed for some different logic or edge case instead.

In this sense, safety is a resource rather than a requirement, and if you learn that a previously unsafe operation is now safe, because the real world circumstances changed around you, you are free to have your program units do the previously-unsafe -now-safe thing without needing to remove expensive abstractions that had been set up to cause the previous notion of safety to be a consequence of your program.


Sounds like you would be better suited using some form of dependently typed system as far as type systems go.

If I understand you correctly now, a functional language with no real type system (and thus no such compiler enforced constraints) like Elixir would be imperative in your book and therefore more suitable to facilitate constantly changing business requirements.

Thanks for taking the time to detail your thoughts for me!


Why is this downvoted? It's pretty extensive and well thought-out, which should be upvoted.

If you disagree, post a rebuttal.


Because these language wars are mostly about people defending their group identity that they've invested a lot of effort into forming. If you want to have focused, fact-based discussions about language tradeoffs, it's more likely to be successful if you stick to small groups of people who are mindful of their egos.


This is a fact-based discussion of language trade-offs. The strength of a statically typed functional language, that you are forced to specify correctness of the program at increasingly abstract levels of the type system, is also its downfall because this is inherently inflexible if the business use case of that software suddenly demands incrementally mutating some part or introducing subtle violations of the constraints the system was designed to enforce. The entire goal of encoding correctness and rendering it difficult or impossible to violate a given notion of correctness is intrinsically at odds with the business purpose of software. This is fundamental. It is a real, physical problem that makes strict functional languages significantly worse suited to business settings than imperative or even object-oriented paradigms, and is supported by language popularity, adoption and success rates.

The fact that classes of bugs prevented by compilers are not very important and are just as adequately caught with lightweight unit tests is more empirical but critical nonetheless.

These are real problems with the arguments in favor of strict functional programming. But instead of engaging with them, they are disingenuously called “language wars” as if they are less legitimate just by using this phrase to describe them.


> This is a fact-based discussion of language trade-offs.

I'm sorry, but it's an opinion-based discussion. No hard facts were presented here. While I see the reasoning behind such opinion, it directly contradicts opinion of pure FP proponents and somewhat contradicts my own experience.

> the business use case of that software suddenly demands incrementally mutating some part or introducing subtle violations of the constraints the system was designed to enforce

Sure, sometimes it's very convenient to add quick hacks, but there is definitely a tradeoff from maintainability perspective. I wouldn't like to work on a codebase full of mutable state and constraints broken in unprincipled ways. On the other hand, I never used Haskell and religiously functional Scala, so maybe I underestimate the scale of the problem. For me Scala with immutable collections, ADT, lenses, IO, typealiases and typeclasses as extension mechanism served extremely well. Could you please provide few concrete examples of type system abuse?


The GP meant that the comment was downvoted because of "language wars" downvoters, not that it was language-wary itself. It did take me two readings to realize that, because I was going in with my own bias.


Sure, but it's also more likely to be successful if you remind people to mind their biases.


This is my same experience except with Clojure. It’s pretty much equivalent to well written JavaScript. Actually no, the latter is usually cleaner and clearer.


>I feel learning Haskell was worthless. It did not teach me anything [..]

Did you already know most of it from Scala?


I learned Haskell first, then Scala later for a job.


That's interesting. I reached a similar conclusion, but I entirely credit learning Haskell for getting there.

I thought I had some idea about controlling state and writing composable systems before, but I see now how rudimentary and flawed it was. Maybe you just got it quicker.


Thank you. This is an important point that deserves to be discussed more.

Would you mind sharing what business domain you were working in? I’ve seen static FP being used/popular in finance but not much elsewhere.

Also, do you have a favourite language now?


Jobs that exclusively or almost exclusively used Haskell & Scala: (1) backend engineering for a large bank (you can likely guess), (2) machine learning at a large education technology company, (3) machine learning at an ad tech company.

My favorite two languages are Python and C. There are certain things I like about Rust, Go and Julia.

I dislike Java and C++ (just personal preference).

I dislike Scala a ton. Really disergonomic and overly complicated.

I like Haskell a lot. Very clean, fun to write, it just doesn’t confer any serious advantages over other language choices and does suffer from difficult-to-extend designs in business use cases, but probably very good for academic work, pure software or research projects. It’s very nice language, I just wish it wasn’t hyped as a transformational way of thinking or as a panacea for all the normal annoying problems with business software.


Check out https://haskellcosm.com with list of companies by area.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: