2016-11-05 5 views
1

Ich frage mich, wie man eine Reihe von Konstanten basierend auf einer Liste von Namen generieren kann.Erzeuge eine Datendeklaration mit TemplateHaskell

Ich begann mit diesem Arbeitsbeispiel:

ConstantCreation.hs

module ConstantCreation where 

import Language.Haskell.TH 

createConstant :: String -> Q [Dec] 
createConstant constantName = do constantType <- newName constantName 
           constant  <- newName constantName 
           return [ DataD [] 
              constantType [] 
              [NormalC constant []] 
              []      ] 

MyConstants.hs

{-# LANGUAGE TemplateHaskell #-} 

module MyConstants where 

import ConstantCreation 

$(do constantsDeclarations <- mapM createConstant 
             [ "MyFirstCustomConstant" , 
             "MySecondCustomConstant" ] 
    return $ mconcat constantsDeclarations) 

Aber die Dinge schwierig, wenn ich versuche, eine deriving Show hinzuzufügen.

Ich versuchte zunächst die Funktion createConstant wie folgt zu ändern:

createConstant constantName = do constantType <- newName constantName 
           constant  <- newName constantName 
           return [ DataD [] 
              constantType [] 
              [NormalC constant []] 
              [GHC.Show.Show]   ] 

wie vorgeschlagen, wenn ich den Befehl runQ [d|data MyConstant = MyConstant deriving Show|] in GHCi laufen, aber es führt den Fehler Not in scope: data constructor ‘GHC.Show.Show’

Also meine Funktion wie ich versuchte, definiere dies:

createConstant constantName = [d|data $(ConT $ newName constantName) = $(NormalC (newName constantName) []) deriving Show|] 

aber dann hatte ich folgende Fehlermeldung:

Es wäre wirklich schade, Instanzen manuell definieren zu müssen, also frage ich mich, was schlecht läuft.

Vielen Dank für eine Beratung oder Erklärung.

+0

Was ist'EleveConstr'? – Sibi

+0

Was ist 'GHC.Show.Show'? Wahrscheinlich möchten Sie, dass die TH-Spleißstelle den Namen darstellt - ''' Show 'oder' showCon <- mkName "Show" ' – user2407038

+0

@Sibi Ich habe den Code korrigiert. Ich änderte den ursprünglichen Code, um das Beispiel zu dokumentieren, vergaß es aber. – Echologie

Antwort

1

Sie können ''Show verwenden, um die Type mit dem Namen zu erhalten, der sich im Geltungsbereich befindet.

{-# LANGUAGE TemplateHaskell #-} 

module Constant where 

import Language.Haskell.TH 

createConstant constantName = do 
    tname <- newName constantName 
    cname <- newName constantName 
    return [DataD [] tname [] [NormalC cname []] [''Show]]