Surely transactions are a pretty good example of where functional core / imperative shell is a good guide. You really don't want to be doing arbitrary side effects inside your transaction because those can't be backed out. Check out STM in Haskell for a good example.
I'd go a little further, though? Transactions have to be able to fail at the very last step. That could just be the "commit" stage. Everything up to that point could have been perfectly fine, but at commit it fails. More, the time of execution of that commit could be fairly far removed from the time of starting the transaction.
To that end, any style that tries to move those two time periods closer together in code is almost doomed to have some either hard to reason about code, or some tough edge cases that are hard to specify.
(Granted, I'll note that most transactions that people are dealing with on a regular basis probably do open and close rather close to each other.)
I meant only that there is no styling that can fix it. Some transactions will flat out fail partially done and have to be kicked to a reconciliation process to fix.
I grant that for things that are purely informational, this is not necessarily as accurate. But as the things reasoned about in a program get larger and larger, transactions span longer and longer timelines. With "all or nothing" not being nearly as clear cut as it is in smaller examples.
My go to examples are things like vending machines. (Granted, that almost certainly just shows my bias for state machines all the way down.)