I've just started to use Template Haskell (I've finally got a use case, yay!) and now I'm cognitively stuck.
What I'm trying to do is generating a singleton datatype declaration of the form
data $V = $V deriving (Eq,Ord)
starting from a name V
(hopefully starting with an uppercase character!). To be explicit, I'm trying to write a function declareSingleton
of type String -> DecsQ
(I should mention here I'm using GHC 7.6.1, template-haskell version 2.8.0.0) such that the splice
$(declareSingleton "Foo")
is the equivalent of
data Foo = Foo deriving (Eq,Ord)
I've got the following code working and doing what I want, but I'm not very happy with it:
declareSingleton :: String -> Q [Dec]
declareSingleton s = let n = mkName s in sequence [
dataD (cxt []) n [] [normalC n []] [''Eq,''Ord]
]
I was hoping to get something like the following to work:
declareSingleton :: String -> Q [Dec]
declareSingleton s = let n = mkName s in
[d| data $n = $n deriving (Eq,Ord) |]
I've tried, to no avail (but not exhaustively!), various combinations of $s
, $v
, $(conT v)
, v
, 'v
so I have to suppose my mental model of how Template Haskell works is too simplistic.
Am I missing something obvious here, am I confusing type names and constructor names in some essential way, and can I write declareSingleton
in a nice(r) way?
If so, how; if not, why not?
(Side remark: the Template Haskell API changes rapidly, and I'm happy for that - I want this simple type to eventually implement a multi-parameter type class with an associated type family - but the churn the API is currently going through doesn't make it easy to search for tutorials! There's a huge difference how TH was implemented in 6.12.1 or 7.2 (when most of the existing tutorial were written) versus how it works nowadays...)