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