
On 2015-06-27 at 14:56:33 +0200, David Fox wrote: [...]
I've had success with a slightly different "How":
What was your concrete use-case btw?
Phase 1: Replace FilePath with a type class, with instances for the old FilePath (i.e. String) and the new implementation.
what would that comprise in the FilePath case? I assume adding a transitional class whose methods are not exposed (and whose typeclass name is exported from some GHC-specific internal-marked module)? i.e. class IsFilePath a where privateToFilePath :: a -> FilePath privateFromFilePath :: FilePath -> a instance IsFilePath FilePath where privateToFilePath = id privateFromFilePath = id instance IsFilePath [Char] where privateToFilePath = System.IO.toFilePath privateFromFilePath = System.IO.fromFilePath ? as well as changing a lot of type-sigs in base & filepath from e.g. writeFile :: FilePath -> String -> IO () openTempFile :: FilePath -> String -> IO (FilePath, Handle) to writeFile :: IsFilePath a => a -> String -> IO () openTempFile :: IsFilePath a => a -> String -> IO (a, Handle) ?
Phase 2: Wait until a suitable amount of hackage builds without the string instance.
I can see Stackage helping with that by using a custom GHC which lacks the legacy `IsFilePath [Char]`-instance. So I'd be optimistic that Phase2 could be accomplished within one year for the Stackage-subset of Hackage.
Phase 3: Deprecate the String instance - move it to an old-filepath package.
Phase 4: Replace the type class with the new implementation
I assume this means getting rid again of the typeclass, and changing the type-sigs back to i.e. writeFile :: FilePath -> String -> IO () openTempFile :: FilePath -> String -> IO (FilePath, Handle) (but now with with the new opaque `FilePath`)?
This way the new implementation is available immediately, packages can begin converting at once, benefits can be assessed.
This scheme seems feasible at first glance, as long as the typeclass doesn't start spreading across packages and find its way into type-sigs (in which case it'd become more disruptive to get rid of it again). Otoh, I'm not sure (assuming I understood how your scheme works) it can be avoided to have the typeclass spread, since if not every API that now has `FilePath` arguments in their type-sigs gets generalised to have `IsFilePath a => a` arguments instead, we can't reach the goal of "Phase 2". But I suspect that I didn't fully understand how your proposed transition scheme works exactly... so please correct me where I got it wrong! Cheers, hvr