2

山かっこでコンマ区切りの値のペアのパーサーを記述したいと思います。私はそれを次のアプローチで動作させることができました:

pair p1 p2 = do
    x1 <- p1
    comma
    x2 <- p2
    return (x1, x2)

data Foo = Foo (Bar, Bar)

foo :: Parser Foo
foo = Foo <$> (angles $ pair bar bar)

ただし、Fooコンストラクターでは、タプルではなく2つのパラメーターを使用することをお勧めします。

data Foo = Foo Bar Bar

そのようなパーサーを書くための最良の方法は何ですか?理想的には、このような標準のパーセクパーセクを再利用anglesし、可能な限りアプリケーションを使用したいと思います。

4

1 に答える 1

8

そのようなパーサーを書くための最良の方法は何ですか?理想的には、このような角度の標準的なパーセクパーサーを再利用し、可能な限りアプリケーションを使用したいと思います。

適用可能なスタイルでは、パーサーは次のようになります。

foo = angles $ Foo <$> bar <* comma <*> bar

裏返しにすると、abarが解析され、次にacommaが破棄され、別のが解析された2つbarのにコンストラクターFooが適用されbarます。angles最後に、すべてがコンビネータにラップされるため、フォームの文字列が

< bar , bar >

解析されます(barおそらく末尾の空白を消費するはずです)。

1つの結果を無視してパーサーを*>および<*適用可能なコンビネーターと組み合わせると、コンビネーターが不要になりpair、任意の数の引数を取るコンストラクターに簡単に一般化できます。

CA McCannがコメントで述べたように、先頭のトークンを無視したい場合は、コンビネータ((<$)GHCのFunctorクラスの実装の一部であり、デフォルトの実装ですが、言語標準の一部ではありません)も役立ちます。(<$) = fmap . constそれを使って、あなたは書くことができます

Foo <$ ignoreMe <*> bar <* comma <*> baz

これは括弧を使用するよりも優れています

Foo <$> (ignoreMe *> bar) <* comma <*> baz

またはpure

pure Foo <* ignoreMe <*> bar <* comma <*> baz

それなしで何らかの形で必要とされるように。

于 2012-12-28T10:55:04.407 に答える