The following doesn't compile:
import Language.Haskell.TH
makeAlpha n = [d| data Alpha = Alpha $(conT n) deriving (Show, Read) |]
I can't make out what the error means at all:
Can't derive instances where the instance context mentions
type variables that are not data type parameters
Offending constraint: Show t_d
When deriving the instance for (Show Alpha)
In the Template Haskell quotation
[d| data Alpha = Alpha $(conT n) deriving (Show, Read) |]
In the expression:
[d| data Alpha = Alpha $(conT n) deriving (Show, Read) |]
Is it possible to do derivations like this?
This problem arises because TH quotes are type checked when they are compiled, with splices replaced by variables. This is usually a good idea, because it allows many kinds of problems to be detected before the splice is run, but in some cases this can make the compiler wrongfully reject a splice that would generate valid code.
In this case, this means that the compiler tries to check this code:
data Alpha = Alpha t deriving (Show, Read)
This doesn't work because the derived Show
and Read
instances need to use Show
and Read
for t
, but since t
is not a type parameter of Alpha
, it cannot add the necessary constraints. Of course, when this splice is run, t
is replaced by a concrete type, so the appropriate instances will be available without the need for any constraints, so this is one of the cases where the compiler is being over-cautious.
The workaround is to not use quoting, but instead use TH combinators, which are not subject to these extra checks. It's messy, but it works:
makeAlpha n = sequence [dataD (cxt []) alpha []
[normalC alpha [strictType notStrict (conT n)]] [''Show, ''Read]]
where alpha = mkName "Alpha"
There has been some talk about relaxing the checks done on quotes, but for now you'll just have to deal with it.
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