FWIW, I've also never been able to design a large project in Haskell (a la darcs), whereas I could write fairly large projects in OCaml without much awkwardness. I suspect the ability to "cheat" with mutability outweighs in practical terms the theoretical elegance and enjoyment of programming in Haskell.
You'll find, though, that it's very easy to make a sequence of mutations become one pure operation, and the ST machinery lets you keep that sequence encapsulated. This is how building a vector works. In a new state thread, you allocate the vector. You run a pure function to generate the nth element. You bit-bang that into memory. When you're at the end of the vector, you freeze the vector into an immutable vector and return it. The final signature is "Length -> (Index -> Value) -> Vector of Values". Totally pure to the outside world, mutable internally. And the type system keeps the mutation part safe!
So while the first approach you try with Haskell should be actual pure code, you still have the tools you need to be as impure as you need to be. And you can still keep your program type safe, if you want.