Я только начал использовать Template Haskell (наконец-то у меня есть пример использования, ура!), и теперь я когнитивно застрял.
То, что я пытаюсь сделать, это создать одноэлементное объявление типа данных формы
data $V = $V deriving (Eq,Ord)
начиная с имени V
(надеюсь, начиная с прописной буквы!). Чтобы быть явным, я пытаюсь написать функцию declareSingleton
типа String -> DecsQ
(здесь я должен упомянуть, что я использую GHC 7.6.1, template-haskell версии 2.8.0.0), чтобы соединение
$(declareSingleton "Foo")
является эквивалентом
data Foo = Foo deriving (Eq,Ord)
У меня есть следующий код, который работает и делает то, что я хочу, но я им не очень доволен:
declareSingleton :: String -> Q [Dec]
declareSingleton s = let n = mkName s in sequence [
dataD (cxt []) n [] [normalC n []] [''Eq,''Ord]
]
Я надеялся получить что-то вроде следующего:
declareSingleton :: String -> Q [Dec]
declareSingleton s = let n = mkName s in
[d| data $n = $n deriving (Eq,Ord) |]
Я пробовал, но безрезультатно (но не полностью!), различные комбинации $s
, $v
, $(conT v)
, v
, 'v
, так что я должен предположить, что моя ментальная модель работы Template Haskell слишком упрощена.
Я упускаю здесь что-то очевидное, не путаю ли я имена типов и имена конструкторов каким-то существенным образом, и могу ли я написать declareSingleton
красиво (r)?
Если да, то как; если нет, то почему?
(Дополнительное замечание: Template Haskell API быстро меняется, и я рад этому — я хочу, чтобы этот простой тип в конечном итоге реализовал многопараметрический класс типов со связанным семейством типов — но отток API, через который в настоящее время проходит API, не Это упрощает поиск туториалов!Существует огромная разница в том, как TH был реализован в 6.12.1 или 7.2 (когда было написано большинство существующих туториалов) по сравнению с тем, как он работает сейчас...)