2011-12-31 1 views
8

Ниже не компилируется:Template Haskell объявления данных, которые получают Показать

import Language.Haskell.TH 
makeAlpha n = [d| data Alpha = Alpha $(conT n) deriving (Show, Read) |] 

Я не могу понять, что означает, что ошибка у всех:

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) |] 

Можно ли делать выкладки как это?

+0

Я думаю, проблема может заключаться в том, что она пытается получить экземпляры до того, как она получит * n *; т. е. пытается расширить ваш сплайсинг, чтобы содержать экземпляры, но не может, потому что не знает, как выглядит '$ (conT n)'. Не уверен. – ehird

+0

Я так же думал, но я часто не могу быть уверен, что разрешено, а не с Template Haskell ... В этом сценарии я думаю, что очевидно, что он еще не может получить экземпляры, и ему нужно дождаться использования функции для расширения , Это ошибка? – Ana

+0

Хм, подождите, не должно быть 'data Alpha = $ (conT n)' или что-то еще? Я думаю, что у вас сейчас есть ошибка типа, по крайней мере, от взгляда на [определение 'Dec'] (http://hackage.haskell.org/packages/archive/template-haskell/2.6.0.0/doc/html /Language-Haskell-TH-Syntax.html#t:Dec). – ehird

ответ

7

Эта проблема возникает из-за того, что котировки TH проверяются по типу при их компиляции с заменой переменных на переменные. Обычно это хорошая идея, поскольку она позволяет обнаруживать множество проблем, прежде чем запускается сращивание, но в некоторых случаях это может заставить компилятор неправомерно отклонить сплайсинг, который будет генерировать действительный код.

В данном случае это означает, что компилятор пытается проверить этот код:

data Alpha = Alpha t deriving (Show, Read) 

Это не работает, потому что полученные Show и Read экземпляры должны использовать Show и Read для t, но поскольку t не является параметром типа Alpha, он не может добавить необходимые ограничения. Конечно, при запуске этого сращивания t заменяется конкретным типом, поэтому соответствующие экземпляры будут доступны без необходимости каких-либо ограничений, так что это один из случаев, когда компилятор чрезмерно осторожен.

Обходной путь - не использовать цитирование, а вместо этого использовать комбинаторы TH, которые не подлежат этим дополнительным проверкам. Это грязно, но это работает:

Там было some talk about relaxing the checks done on quotes, но сейчас вам просто придется иметь дело с ним.