I'm trying to do the following, but constantly running into parse errors while compiling this source-code:
instance FromRow Job where
{-# DEPRECATED fromRow "Please do not depend on the FromRow instance of the Job type. It does not handle optional features, such as job-results and job-workflows. Depending upon your scenario, use 'jobRowParserSimple' or 'jobRowParserWithWorkflow' directly." #-}
fromRow = jobRowParserSimple
Is it possible in Haskell to do this? How?
I am unable to realize what you seek.
I can only suggest a variant: we can make GHC raise an error when the instance is used, unless the user of the instance confirms that they really want to enable the deprecated instance.
This is not an ideal solution, but I could not find anything closer to the goal.
Anyway, here's how it is done. We first define, in the library, some boilerplate class and instances:
{-# LANGUAGE DataKinds, TypeFamilies, UndecidableInstances #-}
import GHC.TypeError
class MakeError a
instance
(TypeError (Text "Please do not depend on the FromRow instance of the Job type. It does not handle optional features, such as job-results and job-workflows. Depending upon your scenario, use 'jobRowParserSimple' or 'jobRowParserWithWorkflow' directly."))
=> MakeError Job
Add here further instances as needed, one for each deprecation you need.
Then, still in the library code, we add a class with an overlappable instance, referring to MakeError which will generate the error message.
class EnableDeprecated a
instance {-# OVERLAPPABLE #-} MakeError a => EnableDeprecated a
Finally, still in the library code, we add the instance we want to deprecate. Here I defined a dummy class, type, and instance.
class FromRow a where
fromRow :: a
data Job
-- Note the deprecation constraint.
instance EnableDeprecated Job => FromRow Job where
fromRow = undefined
Finally, after having completed the library code, we consider the user code. Here's a dummy test using the deprecated instance.
test :: Job
test = fromRow
This user code will trigger an error, showing the error message mentioning the deprecation.
If the user wants to disable the deprecation, they can add the following instance:
instance EnableDeprecated Job
No more errors are now raised.
This solution is not ideal for many reasons. The main issue here is that we rely on overlapping instances, so it is crucial that the last instance EnableDeprecated Job is in scope everywhere, otherwise we might getting the deprecation error, even when the instance is present elsewhere. Note that this is an orphan instance, which makes the overlapping machinery fragile: the burden is on the programmer to keep this instance on scope everywhere.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With