2011-09-27 6 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

私はTemplate Haskellウィザードではありませんが、テンプレート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'を使って' Name'を 'String'から作ります。私は例を追加しました。私は 'newName'を使っているかもしれないと思います。最後に名前が一意であることを確認するためにいくつかのものを追加しています。':info'はそれを表示しません。しかし、あなたは ':browse'を使ってそれを見ることができます。 – hammar

+0

ありがとう!これは私の問題だった。 – Xodarap