If I were to pick one, I’d have to say parallelisation/concurrency. It’s a recent problem really, because for much of the history of software, there was only one CPU or core to execute anything on. This fact, along with the increase in available RAM seems to be the driver towards the functional declarative style in the industry as a whole. Mental models of computing where the programmer thinks their computer is still doing one instruction at a time are really no longer valid.The first thing you get from functional programming is immutability. This gives you a guarantee that the value you are using isn’t going to be changed by some other thread while you’re performing an operation on it. This eradicates a huge group of bugs that are not only really difficult to fix but also really difficult to replicate sometimes. It removes the ‘need’ to add locks into pure code but also provides other shared state options such as Software Transactional Memory and mutable container concepts such as MVars for effectful code that needs shared state.One of the great things about working in a functional language, rather than just in a functional style in an imperative language, is that you have certain guarantees about the libraries that you’re using. They cannot or should not be changing the state that they give you. It’s one thing to do the right thing yourself, but unless you are writing all those libraries yourself as well, you have no guarantees.The other concurrency thing you get from working in a functional declarative language is the ability to write the problem definition and not the mechanics of the solution. This means that rather than writing imperative for loops, you can write lazy declarative maps and folds/reducers. This separates the problem definition from the execution. You as the programmer don’t care how the machine iterates through the collection, just that it executes the function you provide for each element.This empowers the language designers to decide what the best way of accomplishing your task would be, at both compile time and again at runtime. The aim of the game is knowledge encapsulation. If some new technique of getting to the same result faster is discovered, you don’t have to modify your code to see the benefits. Of course you can also optimise by ‘hinting’ to the compiler, for example by using the parallel library in Haskell and computing the result across multiple threads.Of course doing anything on a small case is possible and we work in an industry where almost anything is possible. This sometimes monopolises the discussion around best practices, but I’m generally concerned with larger projects. Less so about what can be shown to work at the small scale, more so about what can be shown to work at every scale.