10

私は Template Haskell で遊んでいます。レコードのデフォルトの初期化子を作成できる準クォーターを作成したい、つまり次のようなもの

[record| data Config = { shouldDoX = True; featureY :: Integer, optionZ = Nothing } |]

関数を作成する必要があります

defaultConfig = Config { shouldDoX = True, optionZ = Nothing }

基本的にはデータ宣言と同じ構文で、デフォルト値で拡張されています。現在recordはカスタムの QuasiQuoter ですが、内部には自分自身を解析したくない式と型があります。理想的には、中括弧内のブロックをステートメントに分割し、 and を探すだけで済み=ます::

[e| ...|]そこで、 orで引用するのと同じことを効果的に行う関数を探してい[t| ...|]ます。Hoogle で関数を検索しましたが、何String -> ExpQString -> Q Exp見つかりませんでした。

私が何を探しているのかよくわからなかった場合:私は QuasiQuoters について知っています。私が述べたように:record QuasiQuoter です。準クォーターに渡される文字列には、式 ( などNode 7 (Node 8 Nil Nil) Nil) とタイプ (Trueまたはなど) が含まれていMaybe (Either A B)ます。私はこれらを自分で解析できますが、文字列を のような引用符に渡したのと同じように、それを実行する関数があることを願っています[e|...|]

だから:式を文字列として、またはタイプを文字列としてフィードでき、適切なExpまたはTypeオブジェクトを返す関数を探しています。コンテキストに基づいて式または型を評価する必要があるため(引用と同じように)、Qモナドに存在する必要があると思います。

functionOfMyDreams "Node 7 (Node 8 Nil Nil) Nil" :: Q Exp
4

2 に答える 2

1

あなたは正しい考えを持っていますが、それは次のような関数になりますString -> Q [Dec]

quasiquoter を作成するには、型の 4 つの関数を持つQuasiQuoterString -> Q Blah型の値を作成する必要があります。Blahは、スプライシングする Template Haskell 型です。

あなたの場合、宣言クォーターを定義するだけで済みます。

quoteRecord :: String -> Q [Dec]
quoteRecord = ...

record :: QuasiQuoter
record = QuasiQuoter (error "record is not a expression quoter")
                     (error "record is not a pattern quoter")
                     (error "record is not a type quoter")
                     quoteRecord

その後、別のファイルでレコード準引用符を使用できます

[record| ... |]

Haskell wikiには良いウォークスルーがあります

文法から quasiquoter を生成するBNFC-metaもチェックしてみてください。

于 2013-03-27T17:03:53.820 に答える