Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Template Haskell data declarations that derive Show

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?

like image 538
Ana Avatar asked Dec 31 '11 18:12

Ana


1 Answers

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.

like image 64
hammar Avatar answered Nov 03 '22 23:11

hammar