Michael Litchard
Michael Litchard

Reputation: 200

How do I capture the named value created by this TH code

Here's my Template Haskell code

objectGIDDeclaration :: String -> Integer -> Q [Dec]
objectGIDDeclaration dnameSTR gid = pure fDec
 where
   dname = dnameSTR <> "GID"
   fDec = [fSig]
   Sig = ValD fname objectType []
   fname = VarP (mkName dname)
   objectType = NormalB (AppE constructor value)
   constructor = ConE (mkName "GID")
   value = LitE (IntegerL gid)

This is what it does

objectGIDDeclaration "foo" 3

this creates a named value fooGID GID {unGID = 3}

I have some other Template Haskell code

objectLabelDeclaration :: String -> Lexeme -> Q [Dec]
objectLabelDeclaration dnameSTR object = pure fDec
  where
    dname = dnameSTR <> "Label"
    fDec = [fSig, value]
    fSig = SigD fname objectType
    vPattern = VarP (mkName dname)
    value = ValD vPattern body []
    constructor = ConE (mkName "ObjectLabel")
    body = NormalB (AppE constructor lexeme)
    lexeme = UnboundVarE (mkName (show object))
    objectType = ConT (mkName "ObjectLabel")
    fname = mkName dname

Here's what it does

objectLabelDeclaration "foo" CABINET

ghci> fooLabel ObjectLabel {_unObjectLabel = CABINET}

Here's what I would like to do but don't know how

mapM someFunction ["foo","bar","baz"]

[(fooLabel,fooGID),(barLabel,barGID),(bazLabel,bazGID)]

the first value has the following type

   newtype ObjectLabel 
      = ObjectLabel {_unObjectLabel :: Lexeme} deriving stock 
         (Eq,Ord,Show)

the second value has the following type

  newtype GID a = GID {unGID :: Int}
      deriving stock (Show, Ord, Eq)

so I am looking to generate a [(ObjectLabel, GID Object)]

I did just try this

objectLabelDeclaration :: String -> Lexeme -> Q ([Dec],Name)

thinking it was the Name I wanted. Is it? Should I figure out another way to capture the Name?

tips tricks and suggestions welcome

Edit: I think I need an Exp not a Q [Dec]. Currently pulling that thread.

Edit: Don't think so

Upvotes: 2

Views: 79

Answers (2)

K. A. Buhr
K. A. Buhr

Reputation: 50819

You don't have to take any special steps to capture names in Template Haskell code. Names created with mkName are captured by default, as in the following example:

{-# LANGUAGE TemplateHaskell #-}
import Language.Haskell.TH

-- foo = 42
$(pure [ValD (VarP (mkName "foo")) (NormalB (LitE (IntegerL 42))) []])

-- main = print foo
main = print $(pure (VarE (mkName "foo")))

So, it should be as simple as writing:

someFunction :: String -> Q Exp
someFunction tag
  = pure $ TupE [Just (VarE (mkName label)), Just (VarE (mkName gid))]
  where label = tag <> "Label"
        gid = tag <> "GID"

Upvotes: 0

Code-Apprentice
Code-Apprentice

Reputation: 83517

If I understand your question correctly, one option is to simply apply your two functions to the input:

someFunction x = (objectLabelDeclaration x, objectGIDDeclaration x)

Upvotes: 0

Related Questions