6

私は Template Haskell を使い始めたばかりで (ようやくユースケースを手に入れました!)、今は認知的に立ち往生しています。

私がやろうとしているのは、フォームのシングルトンデータ型宣言を生成することです

data $V = $V deriving (Eq,Ord)

名前からV始めます (できれば大文字で始めてください!)。明確にするために、私はdeclareSingletonスプライスString -> DecsQ

$(declareSingleton "Foo")

と同等です

data Foo = Foo deriving (Eq,Ord)

次のコードが機能し、必要なことを実行していますが、あまり満足していません。

declareSingleton :: String -> Q [Dec]
declareSingleton s = let n = mkName s in sequence [
        dataD (cxt []) n [] [normalC n []] [''Eq,''Ord]
   ]

次のようなものが機能することを望んでいました。

declareSingleton :: String -> Q [Dec]
declareSingleton s = let n = mkName s in 
    [d| data $n = $n deriving (Eq,Ord) |]

$s$v$(conT v)vのさまざまな組み合わせを試してみましたが、役に立ちませんでした (ただし、すべてを網羅しているわけではありません!) 'v

ここで明らかな何かが欠けていますか? 本質的な方法で型名とコンストラクター名を混同してdeclareSingletonいませんか?

もしそうなら、どのように; そうでない場合、なぜですか?

(余談: Template Haskell API は急速に変化します。私はそれを喜んでいます。この単純な型に、関連付けられた型ファミリを持つマルチパラメーター型クラスを最終的に実装してもらいたいのですが、API が現在経験している変化はそうではありません。チュートリアルを簡単に検索できます! 6.12.1 または 7.2 での TH の実装方法 (既存のチュートリアルのほとんどが作成されたとき) と、現在の動作方法には大きな違いがあります...)

4

2 に答える 2

4

テンプレート Haskellのドキュメントから:

代わりにスプライスが発生する可能性があります

  • 表現; 結合された式は Q Exp 型でなければなりません
  • タイプ; スプライスされた式は Q Typ 型でなければなりません
  • トップレベルの宣言のリスト。結合された式は Q 型でなければなりません [12 月]

たとえば、現在のバージョンの Template Haskell ではコンストラクタ名を単純につなぎ合わせることができません。

このユースケースを単純化するためにできることはあまりないと思います(宣言全体を文字列として構築し、それをDecvia toDecin に変換することを禁止しますhaskell-src-meta)。

宣言のさまざまな部分を単純にローカル変数にバインドすることを検討してください。より冗長になりますが、コードが少し読みやすくなります。

declareSingleton :: String -> Q [Dec]
declareSingleton s = return [DataD context name vars cons derives] where
    context  = []
    name     = mkName s
    vars     = []
    cons     = [NormalC name fields]
    fields   = []
    derives  = [''Eq, ''Ord]
于 2013-03-08T08:37:59.037 に答える