Why are functional programming languages used so rarely in practice?

There are several contributing factors. First, historical. Functional programming first appeared in 1958 with the LISP programming language, and subsequently manifested in ML (1973), Scheme (1975), Erlang (1986), and Haskell (1990), so it had plenty of opportunity to become widely used. But imperative/procedural programming won the day with languages like FORTRAN, ALGOL 58, COBOL, Simula, BASIC, BCPL/B/C, Pascal, etc. Why?

I believe it’s because imperative/procedural programming was much easier to grasp and understand. Functional programming had too much of a “mathematical” and “academic” feel (and it still does). Nobody likes math.

Functional programming was also a fundamental mismatch to the ruling computer architecture of the day: von Neumann. It incurred a severe performance penalty.

Second, educational. Functional programming has rarely been taught to beginners and college freshmen. This is probably related to the above historical point, but again I believe imperative/procedural is easier for beginners.

Third, the arrival of object-oriented programming (OOP) with Smalltalk (1972), C++ (1980), Ruby (1993), and Java (1995) cemented imperative/procedural programming forever more. OOP, after all, is simply a higher level of abstraction above procedural.

Today, OOP rules the IT industry absolutely. It is impossible to dislodge. While functional programming (FP) has seen a resurgence of late, it is typically used as an adjunct to OOP. We see FP seeping into Java, Python, C#, C++, PHP, etc. with the introduction of first-class functions and closures. We see JavaScript, which is primarily a procedural language, used heavily in a FP manner. We see multi-paradigm Scala embracing FP and OOP. But none of these are pure FP languages.

There is another problem with the incursion of FP into the mainstream: with the exception of Scala, none of these languages strictly support data immutability, which is the defining quality of functional programming. Without immutability, FP loses its most critical advantage.

Even Scala is compromised in this respect. If you can write non-functional OOP code, then where is immutability? For Scala to be truly FP, you must adhere to strict, uncompromising, voluntary discipline, and this is too great a burden for most developers.

This situation can only be resolved by the ascendency of languages like Haskell, Clojure, Erlang/Elixir, and F# into the mainstream. In my opinion, this is highly unlikely.