2011-09-27 17 views
11

Sto provando a creare l'anello Z/n (come la normale aritmetica, ma modulo qualche intero). Un'istanza di esempio è Z4:Costruttore dati nel modello haskell

instance Additive.C Z4 where 
    zero = Z4 0 
    (Z4 x) + (Z4 y) = Z4 $ (x + y) `mod` 4 

E così via per l'anello. Mi piacerebbe essere in grado di generare rapidamente queste cose e penso che il modo per farlo sia con il modello haskell. Idealmente mi piacerebbe solo andare $(makeZ 4) e spingerlo fuori il codice per Z4 come ho definito sopra.

Sto avendo un sacco di problemi con questo però. Quando faccio genData n = [d| data $n = $n Integer] ottengo "errore di analisi nella dichiarazione di dati/newtype". Funziona anche se non utilizzo variabili: [d| data Z5 = Z5 Integer |], il che significa che sto facendo qualcosa di strano con le variabili. Non sono sicuro di cosa però; Ho provato a costruirli tramite newName e non sembrava funzionare.

Qualcuno può aiutarmi con quello che sta succedendo qui?

+0

Non sono un mago di Haskell modello, ma sto scommettendo le persone che vorranno vedere il codice Template Haskell. –

risposta

13

Il Template Haskell documentation elenca le cose che è possibile giuntare.

Una giunzione può avvenire in luogo di

  • espressione; l'espressione spliced ​​deve avere tipo Q Exp
  • un tipo; l'espressione spliced ​​deve avere tipo Q Typ
  • un elenco di dichiarazioni di livello superiore; l'espressione impiombato deve avere tipo Q [Dec]

In entrambe le occorrenze di $n, tuttavia, si sta cercando di unire un nome.

Ciò significa che non è possibile farlo utilizzando quotazioni e giunzioni. Dovrai compilare la dichiarazione utilizzando i vari combinatori disponibili nel modulo Language.Haskell.TH.

Penso che questo dovrebbe essere equivalente a quello che stai cercando di fare.

genData :: Name -> Q [Dec] 
genData n = fmap (:[]) $ dataD (cxt []) n [] 
          [normalC n [strictType notStrict [t| Integer |]]] [] 

Sì, è un po 'brutto, ma ci vai. Per usarlo, chiamalo con un nuovo nome, ad es.

$(genData (mkName "Z5")) 
+0

Potrebbe includere un esempio del suo utilizzo? Ho modificato quello che avevi leggermente e ho appena gettato '$ (genData" Foo ")' come livello principale nel mio codice, ma se faccio ': i Foo' in ghci non trova nulla. – Xodarap

+1

@Xodarap: usa 'mkName' per creare un' Name' da una 'String'. Ho aggiunto un esempio. Immagino che potresti aver usato 'newName', che aggiunge alcune cose alla fine per assicurarti che il nome sia unico, quindi': info' non lo mostrerebbe. Dovresti essere in grado di vederlo usando ': browse', però. – hammar

+0

Grazie! questo era esattamente il mio problema – Xodarap

Problemi correlati