Exactly. Debugging is one of the biggest problems with FP, and when you hear some prolific Haskell hackers talking about no longer being capable of understanding code they produced 10 years ago at the peak of their mental performance, it's difficult to commit to it exclusively.
> Debugging is one of the biggest problems with FP
I don't see why that's a problem with FP and not just the lack of tooling in most FP languages. Debugging in F# via Visual Studio is a breeze, and OCaml's time travelling debugger looks pretty good.
I guess if you start using nth-order functional compositions and everything is a recursion, it's super difficult to figure out what is going on from e.g. stack traces or just simple log statements. And often FP programs are more-less solutions to "puzzles" and to understand the solution you need to keep that "puzzle" on mind. Now what are you doing if you have multiple levels of "puzzles" at the same time and you need to connect two separate subsystems via some deep-level information exchange, given there are no mutable variables/singletons for you? I am sure anyone taking FP seriously hits this kind of problems regularly and they often take long time to come up with satisfactory pure implementations.
Just a clarification for anybody else who might be reading this: there absolutely are mutable variables in pure fp languages like Haskell, you just have to explicitly ask for them (and reflect that fact in the type), i.e:
do
x <- newIORef 0
writeIORef x 2
print =<< readIORef x
will print 2. In fact, I'd argue that many times writing programs with mutable state is actually easier in Haskell/etc, especially when it comes to concurrency where something like software transactional memory [0] is invaluable (and more or less practically unusable in other ecosystems), if it fits your constraints.
For F#, is it a debugger designed for F# or just good integration with VS’s .net debugger? If the latter, I should mention that the problem remains even when using C# if your code gets too functional (e.g. getting rid of some LINQ for debuggability is a common trade off).
Indeed there are some quirks in VS 2015 even in C#, like writing a function as a generator isn't as pleasant as it could be. Haven't tried VS 2017 yet. I think we're a little spoiled on .NET though, we've forgotten how bad debugging is in other languages!
Interesting. Where do you hear that? What I've heard (and experienced) is that Haskell makes is easy to come back and understand code written a long time ago (because the language allows one to structure code very clearly).