Disabling deprecated functions

The time has come to remove some deprecated functions from containers. As many know, lots of people ignore deprecation warnings. That means there are probably plenty of people still using the deprecated functions. Right now, the functions work, and give deprecation warnings telling users what alternatives to use. If I simply remove the functions, users will suddenly have to *actually* do something to fix their code, but they *won't* be given any useful information about how to do it. Ideally, GHC would add a REMOVED pragma, but I don't see any sign that that's happening. Pondering that conundrum today, I came up with something that seems to *mostly* solve the problem: -- We need this class to defer the type error to the call site, rather -- than getting it at the definition site. I think it basically takes advantage -- of the delayed resolution GHC uses to support overlapping instances, -- which is kind of gross. class Error (e :: ErrorMessage) instance TypeError e => Error e insertWith' :: Error ('Text "Data.IntMap.insertWith' is gone. Use Data.IntMap.Strict.insertWith.") => (a -> a -> a) -> Key -> a -> IntMap a -> IntMap a insertWith' _ _ _ _ = undefined Now if someone is still using Data.IntMap.insertWith', they'll get an error message, but a useful one. Great! But there are two downsides: 1. An unqualified, unrestricted import of the module will still use up a perfectly good name for as long as the export is still there. 2. User-defined type errors have only existed since GHC 8.0. So for earlier versions, I'd probably need to just remove the functions, in which case the exports depend on the GHC version, which is unfortunate. In these *particular* cases, I suspect the benefits of this hack outweigh the downsides, because unqualified and unrestricted imports of Data.Map and Data.IntMap are fairly rare. What are others' thoughts on the matter? David

I just realized I can do the same thing with older GHC versions,
except with much uglier error messages. So I think I'm going to try
this out as an experiment and see what people think of it in practice.
On Tue, Feb 13, 2018 at 11:06 PM, David Feuer
The time has come to remove some deprecated functions from containers. As many know, lots of people ignore deprecation warnings. That means there are probably plenty of people still using the deprecated functions.
Right now, the functions work, and give deprecation warnings telling users what alternatives to use. If I simply remove the functions, users will suddenly have to *actually* do something to fix their code, but they *won't* be given any useful information about how to do it.
Ideally, GHC would add a REMOVED pragma, but I don't see any sign that that's happening.
Pondering that conundrum today, I came up with something that seems to *mostly* solve the problem:
-- We need this class to defer the type error to the call site, rather -- than getting it at the definition site. I think it basically takes advantage -- of the delayed resolution GHC uses to support overlapping instances, -- which is kind of gross. class Error (e :: ErrorMessage) instance TypeError e => Error e
insertWith' :: Error ('Text "Data.IntMap.insertWith' is gone. Use Data.IntMap.Strict.insertWith.") => (a -> a -> a) -> Key -> a -> IntMap a -> IntMap a insertWith' _ _ _ _ = undefined
Now if someone is still using Data.IntMap.insertWith', they'll get an error message, but a useful one. Great! But there are two downsides:
1. An unqualified, unrestricted import of the module will still use up a perfectly good name for as long as the export is still there.
2. User-defined type errors have only existed since GHC 8.0. So for earlier versions, I'd probably need to just remove the functions, in which case the exports depend on the GHC version, which is unfortunate.
In these *particular* cases, I suspect the benefits of this hack outweigh the downsides, because unqualified and unrestricted imports of Data.Map and Data.IntMap are fairly rare.
What are others' thoughts on the matter?
David
participants (1)
-
David Feuer