文脈自由文法を Greibach Normal Form (GNF) に変換しています。主な変換 (Hopcroft & Ullman による) は、文法のインデックス付き変数に対する一連の反復です。それは本質的に「ステートレス」です。適切なインデックスに対する一連の折り畳みとして実装しました (実装はかなり簡単です)。
gnf :: Ord a => Set (Rule a) -> Set (Rule a)
gnf rl = foldl step1 rl [1..maxIndex rl]
where step1 rl' k = foldl step2 rl' [1..k - 1]
where step2 rl'' j = noLR k (subst rl'' k j)
maxIndex rlは、一連のルール内の最大変数インデックスを返します。subst rl kjは、右辺がjインデックスの変数で始まるルールによって、 kインデックスのルールで置換を実行します。gnfを実行した後、逆の順序で文法の最終パスを実行する必要があります。
問題はnoLRで、左再帰のkインデックス規則で文法を変換します。noLRが適用されるルール (またはkインデックス付きルール)ごとに一意の変数を生成する必要があるため、これは「ステートフル」関数です。だから私はステートフル関数を書いた
noLR :: Ord a => Int -> Set (Rule a) -> State [Sym a] (Set (Rule a))
noLR rl = do (n:ns) <- get; put ns;
let rl' = ... remove left recursion rl n ...
in return rl'
noLRがパラメーターとして取るnを更新するために、 noLRを一緒にシーケンスすることができます。ただし、上記の関数のstep2内でnoLRを実行する方法がわかりません。ステートフルな計算がいくつかの再帰関数内に埋め込まれているため、スキーマでlet ...を使用できないようです。
私がやりたいのは、 nの明示的なスレッド化と同様に、 nを何らかのタイプのグローバル変数にすることです。これは、 step2内で呼び出して更新できます。これが、もともと関数をeta -expansion (for n)。この種の効果を達成するために状態モナド内でgnfを構造化する方法を知っている人はいますか? フォールド内の最後の計算を除いて、他に何も「ステートフル」ではありません。私は「些細な」例で状態モナドを使用することに慣れているだけです。私はむしろ迷っています。