Haskellでは、XMLドキュメントの場合のように、再帰ツリーのデータ型を簡単に作成できます。
data XML =
Text String -- Text of text node
| Elem String [XML] -- Tagname; Child nodes
およびそれに関連するフォールド:
-- Simple fold (Child trees don't see the surrounding context.)
foldt :: (String -> a) -> (String -> [a] -> a) -> XML -> a
foldt fT fE (Text text) = fT text
foldt fT fE (Elem tagname ts) = fE tagname (map (foldt fT fE) ts)
-- Threaded fold for streaming applications.
-- See http://okmij.org/ftp/papers/XML-parsing.ps.gz
foldts :: (a -> String -> a) -> (a -> String -> a) -> (a -> a -> String -> a) -> a -> XML -> a
foldts fT fE_begin fE_end = go
where
go seed (Text text) = fT seed text
go seed (Elem tag children) =
let seed' = fE_begin seed tag in
let seed'' = foldl go seed' children in
fE_end seed seed'' tag
今の私の問題は、HTMLをモデル化するためにツリーデータ型にいくつかの追加の制限を追加する方法がわからないことです。HTMLでは、各要素ノードは正しいコンテキストでのみ表示でき、各要素はその子の異なるコンテキストに対応します。例えば:
- imgのようなボイド要素には空のコンテキストモデルがあり、子を持つことは許可されていません。
- タイトルなどのテキストコンテンツモデルを持つ要素は、子としてテキストノードのみを持つことができます(ネストされたタグは許可されません)
- div要素はPhrasingコンテキストに表示できないため、span要素の子孫になることはできません。
だから私の質問は:
Haskell98でこれらの制限をモデル化するにはどうすればよいですか?(Haskell98モデルは他のプログラミング言語にうまく翻訳されるはずなので、これを尋ねます)
さまざまなコンテキストに対してさまざまなデータ型を作成する必要があるかもしれないと思いますが、これを原則的かつ明確な方法で行う方法がわかりません。迷子になることなくこれを行うにはどうすればよいですか?また、折り畳み関数はどのようになりますか?
GADTなどの最新のGHC機能の使用が許可された場合、モデルはどのようになりますか?
GADTは、制限をタイプチェッカーにプッシュして、折り畳み機能を単純に保つのに役立つかもしれないという予感がありますが、私はそれらの経験があまりありません...
100%機能するソリューションは必要ありません。それは明らかにStackOverflowの説明の範囲を超えているからです。GADTなどをよりよく理解し、残りを自分でできるようになるのに十分なだけです。