One common issue with total functional style is that you must handle all possible errors, even when you know there is no error but cannot explain this to the system.
Let's say you define division so that it requires you to check whether or not the division was successful (not a division by zero). Even in an expression like x/2
you may still have to check for division by zero.
The same goes for the head of an empty list. Maybe you are running head [1,2,3]
or somesuch. You know there will be success and yet you must handle failure.
So when you do know - what to do? Should you propagate this impossibility of failure up the call chain even though it appears impossible?
In many popular languages they throw an exception or error of some sort in these cases, and basically this means the programmer's assumption of non-error was violated.
It seems there is a trade-off here. On the one hand you can assume success to avoid superfluous error checking at compile time but allow runtime failures. Or you can forbid runtime errors but have superfluous compile/check time errors.
It may be that two operators/methods are needed - one that assumes success and one that you must check the result of. It may be possible one day with static analysis to validate uses of the "assumed success" operator/method. Adding extra operators comes with a big cost, too, in the learning curve of the code and the language.