Abstract FilePath Proposal
Mario Blažević
blamario at ciktel.net
Mon Jun 29 02:24:01 UTC 2015
On 06/27/2015 09:37 AM, Herbert Valerio Riedel wrote:
> 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
It's probably better to not export the class at all, only its two
instances and its methods. See below.
> 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".
As long as the typeclass itself is not exported, this is not a big
problem. Every *explicit* type signature would have to contain either a
String or a FilePath. Yes, the transition to the FilePath-only state
would probably be slower, but that is the intended feature, not a bug.
GHC could do more to help with the transition if it allowed the
DEPRECATED pragma on class instances:
instance IsFilePath String {-# DEPRECATED "Use the FilePath type
instead" #-} where ...
The warning would be reported wherever the compiler can statically
determine that the deprecated instance is used.
More information about the Libraries
mailing list