2011-09-27 58 views
11

我正在試圖創建Z/n環(就像正常的算術,但是取模一些整數)。一個示例是Z4:模板haskell中的數據構造函數

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

等等。我希望能夠快速生成這些東西,而且我認爲使用模板haskell的方法就是這樣。理想情況下,我只想去$(makeZ 4),並讓它像我上面定義的Z4一樣代碼。

雖然我有很多麻煩。當我做genData n = [d| data $n = $n Integer]時,我得到「數據/新類型聲明中的解析錯誤」。如果我不使用變量,它確實有效:[d| data Z5 = Z5 Integer |],這意味着我對變量做了一些奇怪的事情。我不確定是什麼;我試圖通過newName構建它們,但似乎也沒有工作。

任何人都可以幫助我在這裏發生了什麼?

+0

我不是一個模板哈斯克爾嚮導,但我打賭誰是希望看到你的模板Haskell代碼的人。 –

回答

13

Template Haskell documentation列出了允許拼接的東西。

剪接可發生在取代

  • 的表達;拼接表達式必須具有類型Q Exp
  • 類型;拼接表達式必須具有類型Q Typ
  • 頂級聲明的列表;拼接表達式類型必須Q [Dec]

$n兩次出現,但是,你要拼接一個

這意味着你不能使用報價和拼接來做到這一點。您必須使用Language.Haskell.TH模塊中提供的各種組合器建立聲明。

我認爲這應該相當於你想要做的。

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

是的,這有點醜,但你去。要使用它,請用新名稱(例如,

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

你能舉一個例子嗎?我稍微修改了一下,只是把'$(genData「Foo」)'作爲頂級代碼投入我的代碼中,但是如果我在ghci中執行':i Foo',它什麼也找不到。 – Xodarap

+1

@Xodarap:使用'mkName'從'String'創建'Name'。我已經添加了一個例子。我想你可能已經使用過'newName',它在最後添加了一些東西以確保名稱是唯一的,所以':info'不會顯示它。不過,您應該可以使用':browse'來查看它。 – hammar

+0

謝謝!這完全是我的問題。 – Xodarap