fortknots
This argument may seem more abstract than what you mention, but in fact it gets to the very heart of why there aren't good unboxed mutable arrays in haskell. In truth, there are. You can convert Immutable Vectors (which are lists with O(1) indexing but no mutation) into Mutable Vectors in constant time using unsafeThaw. The problem is that your code is no longer persistent, and you've risked introducing subtle errors. My biggest problem is that the haskell community seems to look at non-persistent data structures as sacrilegious. As a scientific programmer, that makes me feel like maybe learning haskell wasn't such a good investment after all. But on the bright side, functional programming is on the rise, and I'm confident that all my experience with Haskell will transfer well in the future.
If we have the following function:
foo :: Int -> Int
foo x = x `div` 0
and we want to add debugging, we can do: import Debug.Trace
foo :: Int -> Int
foo x
| trace (show x) False = undefined
| otherwise = x `div` 0
The above will print the value of x before throwing an error due to division by zero. You don't have to make foo return an IO Int or change any other aspect of your program.