> I believe that ideally we'd write everything in FP with no IP whatsoever. So no mutable variables, no pass by reference, no iteration.

> Then IP would be used to wire up components, similarly to controllers in MVP.

This viewpoint was popularized by Gary Bernhardt a while ago as "functional core, imperative shell." [0] Functional paradigms should be used for expressing core logic and transformation of data; code written in this style is side-effect free, "pure," rapidly unit testable in isolation, and even could in principle be executed in one's head, because it's the final expression value that is the goal when working in this paradigm.

Imperative paradigms on the other hand are not interested as much with expressions and values, but rather statement side-effects, behaviors, and the sequencing together of computations (and it's the concept of sequencing together effectful computations that monads attempt to abstract over). It is the glue code that ties together your pure, effect-free logic and embeds those expressions in a context where they actually have some interaction with computing, hardware, and the outside world; otherwise, they would just be formulae sitting in a spreadsheet with no connection to anything whatsoever.

> Attempts can also be made to eliminate IP altogether by providing impure functionality in FP languages by introducing monads for I/O and exceptional behavior, allowing mutation by isolating it in blocks, etc. I believe that makes impure FP languages equivalent to IP, corrupting them and defeating the point of using FP.

This point is interesting. One could argue that monads are in fact a way of preserving purity in FP while still attaining effectful imperative-like behavior, since the monad is "just" an AST or a pure value that describes a sequence of computations that ought to take place, and it's up to the runtime to actually interpret this data structure and execute or realize the effects merely described by the monadic value (I suppose an OOP design patternist would see similarities to a "Command pattern" here); however, Conal Elliot has taken this logic to the conclusion that, if it were the case, then the C language must also be "functionally pure." [1]

> When often programs can be written much more concisely and clearly by avoiding custom types altogether and focusing on data-driven standard types like numbers, strings and JSON run through transformation functions. An obvious example being how Java programs are often bloated and overengineered because they are object-oriented instead of functional. It's amazing to see how so much boilerplate often contains so little actual business logic. And how languages inspired by Java, like C#, often seem to repeat its shortcomings.

Maybe, but there is also a risk of running into the "Primitive Obsession" code smell [2]. If I have a URL, representing that URL as a String now allows malformed URLs or things that are not URLs at all to inhabit that type, reducing the number of static guarantees I can avail myself of; moreover, if I want to extract the scheme, path, etc. from the URL I now have to extract those attributes by way of lower-level text manipulation, substrings, and slices, instead of being able to simply read off those components of the URL from a higher-level representation that actually reifies those components as first-class attributes of a more structured data type.

I find that one of the main differences between Haskell and other languages and their ecosystems is the focus on finding good abstractions. Often I have seen Java or C# or golang interfaces two dozen methods wide. Not only does this break "interface segregation principle" and other SOLID dogmas, making it difficult to write other implementors (and often you just end up with the single implementor, at which point the interface barely abstracts over anything at all), such an overspecified interface tends to generalize poorly to other use cases.

The more you add to your interface, the more you specify and constrain its structure, the less general it becomes; hence TFA's celebration of monads which, having a minimal complete definition of one operator, can be applied to a shockingly wide variety of domains and are widely relied on by the ecosystem because, as an abstraction only a method wide, monads are subject to much less churn or interface breakage over time.

Finding good abstractions is hard, and IMO one of the central problems of writing software. I would summarize the article as observing that in imperative programming, it's possible to proceed naively but expeditiously, papering over the lack of strong and consistent abstractions by just throwing more glue code and flex tape at the problem to paper over any leaks. In Haskell, especially when first designing your types and data structures, the work of abstracting the problem domain adequately is front-loaded and you are forced to think about it up front.

[0] https://www.destroyallsoftware.com/screencasts/catalog/funct...

[1] http://conal.net/blog/posts/the-c-language-is-purely-functio...

[2] https://wiki.c2.com/?PrimitiveObsession