From my perspective, it isn't cut-and-dry. The quick response I give is:
If you are developing a business application and no one dies if something goes wrong for a few hours, the answer is "hell no". Productivity takes a hit for no strong upside to the biz.
If you are developing a safety-critical system, the answer is "maybe". This one is more obvious.
The more complex reasoning is that ultimately, almost every software system has to interface with the outside world in some way. Putting your functional programming layer as your principal interface between your internal and external domains is an extremely high-cost endeavor due to the complexity of handling things you can't predict. If your system is safety-critical, and you have extensive control over the external domain (e.g. dedicated, redundant sensor networks), you might be able to justify this added complexity because you can control many more variables than you would be able to otherwise.
An alternative approach that seems ideal to me at this time is to use imperative techniques as the principal architecture, and then use functional within that domain in the specific cases where it can be justified. Good examples of this would be C#/LINQ, or even invocation of F# from C# (e.g. rules engine). Imperative is extremely good at handling side-effects and managing exceptions. Functional is deterministic if you can keep it on rails. Using both where most suitable w/ interop between seems to be the most productive approach.
A quick corollary could be: "If you are exclusively using functional techniques to build your application, you are probably making a mistake".
I'm writing most of my apps in Elixir which is also functional. I got no problems wiring side effects with it despite it being less imperative than some C#/Java/friends. In fact, I'd write high availability apps on Elixir any day over C# or other OOP/imperative lang. I don't ever want to touch any safety-critical systems though, but I do care about correctness of the business logic. Somehow I have zero interest in Microsoft langs/runtimes in general.
That said, Haskell just feels like a different beast. I also don't know how interop would actually work with these different solutions, would feel like unnecessary complexity if anything. Only to end up losing the benefits of Haskell's strong typing.
I've been struggling to justify spending more time & effort on concepts mostly exclusive to Haskell, only to be able to be productive on it. I keep thinking I should brush up my Elixir skills instead.
> as your principal interface between your internal and external domains is an extremely high-cost endeavor due to the
complexity of handling things you can't predict.
I fail to see why if you believe this is true of haskell, it would not also be true of C#
The funny thing is that software engineering tools exist to relieve programmers of mental overload. This in turn can be used to build more complicated systems, at the cost of another level of mental overload.
So this begs the question: where are the complicated systems written in Haskell that could not have been realized in other languages? Or are Haskell programmers only using the language to sleep better at night?
> Or are Haskell programmers only using the language to sleep better at night?
For me, the balance point lies definitely closer to the latter. I'm not writing hugely more complicated programs in Haskell than I did in Python but I feel much better knowing they're not likely to fall into pieces next time I touch them.