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)

しかし、私はタプルではなく2つのパラメータを取るFooのコンストラクタを好むでしょう:

data Foo = Foo Bar Bar

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

2
nl ru de

2 答え

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

アプリケーションスタイルでは、パーサは次のようになります。

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

内側に出て、 bar が解析され、次にコンマが破棄され、別の bar /code>は2つの解析された bar に適用されます。最後に、すべてが angles コンビネータにラップされるので、フォームの文字列

< bar , bar >

bar は恐らく末尾の空白を消費するはずです)。

Combining parsers ignoring the result of one with the *> and <* applicative combinators eliminates the need for the pair combinator and easily generalises to constructors taking an arbitrary number of arguments.

As C.A. McCann mentioned in a comment, the (<$) combinator (which is part of GHC's implementation of the Functor class, with the default implementation (<$) = fmap . const; but it's not part of the language standard) is useful too, if you want to ignore a leading token. Using that, you can write

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

これはカッコを使用するよりも良いです

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

または pure

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

それがなければ何らかの形で必要となるであろう。

8
追加された
class Functor f where ...(<$):: a - > f b - > f a - `GHC.Base 'で定義されていますinfixl 4 <$
追加された 著者 Daniel Fischer,
また、先行するトークンを無視する場合は、 Foo <$ keywordFoo <*> bar <* comma <*> baz のようなものを使用できます。私は(<$)がどこに定義されているのか、それをどのようにエクスポートするのかを忘れています。
追加された 著者 C. A. McCann,

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

アプリケーションスタイルでは、パーサは次のようになります。

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

内側に出て、 bar が解析され、次にコンマが破棄され、別の bar /code>は2つの解析された bar に適用されます。最後に、すべてが angles コンビネータにラップされるので、フォームの文字列

< bar , bar >

bar は恐らく末尾の空白を消費するはずです)。

Combining parsers ignoring the result of one with the *> and <* applicative combinators eliminates the need for the pair combinator and easily generalises to constructors taking an arbitrary number of arguments.

As C.A. McCann mentioned in a comment, the (<$) combinator (which is part of GHC's implementation of the Functor class, with the default implementation (<$) = fmap . const; but it's not part of the language standard) is useful too, if you want to ignore a leading token. Using that, you can write

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

これはカッコを使用するよりも良いです

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

または pure

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

それがなければ何らかの形で必要となるであろう。

8
追加された
class Functor f where ...(<$):: a - > f b - > f a - `GHC.Base 'で定義されていますinfixl 4 <$
追加された 著者 Daniel Fischer,
また、先行するトークンを無視する場合は、 Foo <$ keywordFoo <*> bar <* comma <*> baz のようなものを使用できます。私は(<$)がどこに定義されているのか、それをどのようにエクスポートするのかを忘れています。
追加された 著者 C. A. McCann,