2009-12-06 5 views
9

私はHaskellのモジュールの構造を反映し、さまざまな種類のが定義されているLanguage.Exts.Annotated.Syntax、からの値を扱うコードを書いている:は定型の回避

data Module l = ... 
data Decl l = ... 
data Exp t = ... 
-- etc 

私がしたいですこれらのデータ構造を歩き回り、さまざまな変換を実行する関数を書くことができるようになりました。共通のデータ型はないので、すべてを行う関数を書くことはできません。私は今取る多くのコードを書いて自分自身を見つけることだが

data Tree l = ModuleT (Module l) 
      | DeclT (Decl l) 
      | ExpT (Exp l) 
      -- etc copy & paste 

:これまでのところ、私は私の変換関数はTree l -> Tree lを行うことができますように、これらのタイプのそれぞれをラップTreeタイプを書いた

Moduleは、ModuleTをラップして関数を呼び出し、結果を再びModuleにアンラップします。私が持っている:

class AnnotatedTree ast where 
    tree :: ast l -> Tree l 
    untree :: Tree l -> ast l 

instance AnnotatedTree Module where 
    tree = ModuleT 
    untree (ModuleT x) = x 
    untree _ = error "expected ModuleT" 

-- etc ad nauseam 

つの質問:

  1. 私は、Language.Exts.Annotated.Syntaxで種類を変更することはできません私はこのことについて間違った道を進んでいますことを考えると?
  2. そうでなければ、この定型文を何とか切り捨てることはできますか?

答えて

6

これらのタイプはすべて、「タイプ可能」および「データ」のインスタンスであるようです。タイプ・ツリーをTypeableとDataのインスタンスに定義し、使用可能なジェネリック・ライブラリー(SYB、uniplate、...)の1つを使用してツリーを容易にトラバースすることができます。

私の個人的なお気に入りはuniplateです。たとえば、ツリーからのすべてのGuardedAltを収集することと同じくらい簡単だろう:

import Data.Uniplate.PlateData 

... 

allGuardedAlts :: Tree l -> [l] 
allGuardedAlts t = [ l | GuardedAlt l _ _ <- universeBi t] 

あなたは、私は同様のことをした私のパッケージgraphtypeを見てみることができます。

+1

ユニプレートは、私が必要としていたもののようです。私は今、私の定型文を廃止しました。 –

+1

このアプローチでは、もはや本当にあなたのツリータイプは必要ありませんか? – Martijn

+0

そうです、私はそうではありません。ツリーリライト機能は、私が気にするタイプごとに1つのrewriteBiアプリケーションのシリーズとして設定できます。 –