1. Define a FutureProofing.hs module that anticipates changes to GHC that are, or now were, inevitable, such as Monad becoming a subclass of Applicative, and "fail" moving out of Monad. I redefine MonadIO to depend on Applicative so that I can use "pure" universally, hiding "return" from Prelude.
2. I have a longish list of things I hide from the Prelude, besides "return" (above). I haven't yet crossed the Rubicon of inhibiting the standard Prelude altogether, but I don't allow myself to use the bad parts.
3. I have a GenericIO.hs module that defines a typeclass that allows me to use any type of string for pathnames or data. This eliminates nearly all boilerplate conversions when dealing with the IO library and anticipates the changes that might eventually come to the standard Prelude.
In short, I expect and anticipate the standard library to improve, and will not have to do much work to exploit those improvements when they do arrive. I steer clear of the pitfalls. And unlike the OP, I try to avoid complicating the problem by adding new things to my universal imports; I don't mind having longish import lists at the heads of my modules (and I always enumerate all the names that I import).