5

myの名前 (階層識別子を表す) を、モナドの非表示状態として保持されるシンボル テーブルの名前 (整数)renameに置き換える関数を書きたいと考えています。StringASTGUIDRenamer

名前のAST a型でパラメータ化された型があります。AST のリーフにある名前のタイプは次のName aとおりです。

data Name a = Name a

これにより、SYB トランスフォーマーでそれらを簡単にターゲットにすることができます。

パーサーは次のように入力されます (簡潔にするためにエラーの可能性は無視します)。

parse :: String -> AST String

rename関数を次のように入力します。

rename :: AST String -> Renamer (AST GUID)

SYB を使用して、トランスフォーマーを使用してすべてName Stringのを にName GUID変換することは可能ですか?

resolveName :: Name String -> Renamer (Name GUID)

からの他のすべての値は、子c Stringc GUID変換し、同じコンストラクターを使用して貼り付けますが、型パラメーターは異なりますか?

everywhereM関数は私が望むものに近いですが、変換はできますが、変換はできませc a -> m (c a)c a -> m (c b)

私のフォールバックソリューション(定型文を手で書く以外)は、型パラメータを から削除し、次のようASTに定義するNameことです:

data Name = StrName String
          | GuidName GUID

名前の変更が入力されるように:

rename :: AST -> Renamer AST

で動作させるeverywhereM。ただし、これにより、名前が変更された後も an が 's をAST保持している可能性が残ります。型システムを使用して、名前が変更されたものは名前しか保持できないStrNameという事実を正式に把握したかったのです。ASTGUID

4

1 に答える 1

2

解決策の 1 つ (期待していたよりも効率が悪いかもしれません) は、AST を のインスタンスにしFunctor、(GHC 7 ではおそらくこれらすべてを派生させることができます)、次のようにします。DataTypeable

import Data.Generics.Uniplate.Data(universeBi) -- from the uniplate package
import qualified Data.Map as Map

rename :: AST String -> Renamer (AST GUID)
rename x = do
    let names = nub $ universeBi x :: [Name String]
    guids <- mapM resolveName names
    let mp = Map.fromList $ zip names guids
    return $ fmap (mp Map.!) x

2 つのポイント:

  1. Nameからビットを削除するのは簡単resolveNameだと思いますが、そうだと思います。
  2. SYB で同等のものに切り替えることもできますがuniverseBi、Uniplate バージョンの方が理解しやすいと思います。
于 2011-06-18T12:40:36.223 に答える