In my limited experience (desktop IDEs, script interpreters), attempts to extract a functional core are usually detrimental:
- the imperative shell requires much more testing in the first place and has more bugs (because of concurrency and event model which maps poorly to functional core), so the "testability" argument does not hold
- the functional core has to be exposed to testing code, violating the natural unit bounds (requires testing implementation instead of interface)
Benefits:
- significantly improved readability - is subjective
- lots of fun
are subjective and usually not worth it.
On the other hand functional utilities are fine (but are usually provided by standard library).
Conclusion
The functional core - imperative shell approach requires a matching domain to be effective. Something where "mutation" is not the main objective.