2017-09-12 6 views
4

に参加するパーサを生成します次の関数を実装:は、別のパーサの出力に受信パーサを実行し、monadically文字列にCSVフィールドのフィールドを解析することを意図し、次の種類や機能、与えられた結果

customCell :: String -> Parser res -> Parser res 
customCell typeName subparser = 
    cell 
    >>= either (const $ unexpected typeName) 
       return . parse (subparser <* eof) "" 

私は私が希望な限りモナドの概念を使用していないと、それは最終的には、特別に、外側のパーサと、内側の結果をマージするためのより良い方法があることを考えるのをやめることはできませんがその失敗に関係して。

誰かが私がそうすることができるか、またはこのコードは何を行うべきかを知っていますか?

PS - タイプの簡略化が適切でない可能性があることと、おそらく私が望むのは、モナドのアイデンティティモナドを置き換えることです。残念ながら、モナドトランスフォーマーについてまだ十分に知りません。

PS2 - とにかく根底にあるモナドは何ですか?

答えて

1

悲しいことに、このような垂直パーサの構成をサポートしているHaskell用のパーサーライブラリまたはパーサージェネレータがないことはわかっています。あなたが書いたようなものは、それが得られるほど良いものです。ダン!

+1

私はあなたが垂直パーサの構成を意味するか分かりません。少し拡大してもらえますか? – gallais

+1

@gallais私が求めているのは、「Parser Foo [Bar]」と「Parser Bar Baz」を「Parser Foo Baz」に変換する方法です。 –

+1

ありがとうございます。このような単純なタイプでは、OPの質問よりもはるかに明確です。解明してくれてありがとう! – gallais

4

@Daniel Wagnerの答えを精緻化する...パーザは通常、Parsecで構築されますが、特定の文字(例:プラス記号や数字)を解析する低レベルのパーサから始め、上にパーサを構築します1つまたは複数の数字を読み取るパーサーに1桁の数字を読み取るパーサーを切り替えるコンビネーターや、「1つ以上の数字」の後ろに「プラス記号」が続く「モナドな解析」などのコンビネーターを使用して、 1つまたは複数の数字 ")。

ただし、各パーサーは、低レベルの桁パーサーでも高次の「加算式」パーサーでも、同じ入力ストリームに直接適用されることを意図しています。あなたは一般的にんが、たとえば、生成する入力ストリームのチャンクをゴブルズパーサを書くStringし、(代わりに、元の入力ストリームの)Stringことを解析し、別のパーサーとされていない何

それらを組み合わせてみてください。これは、Parsecによって直接サポートされていない "垂直構成"のようなもので、不自然でモナドではないように見えます。

としては、コメントで指摘した、縦組成物は(あなたが別の言語の要素や表現の中に埋め込まれた1つの言語を持っているときのように)きれいな全体的なアプローチですが、それが取られ、通常の方法ではありません一部状況がありますParsecパーサによって。

Stringのみを生成するパーサーは、cellパーサが役に立たないことがアプリケーションの最終行です。CSVファイルのためのより有用Parsecのフレームワークは、次のようになります。

import Text.Parsec 
import Text.Parsec.String 

-- | `csv cell` parses a CSV file each of whose elements is parsed by `cell` 
csv :: Parser a -> Parser [[a]] 
csv cell = many (row cell) 

-- | `row cell` parses a newline-terminated row of comma separated 
-- `cell`-expressions 
row :: Parser a -> Parser [a] 
row cell = sepBy cell (char ',') <* char '\n' 

、あなたは正の整数を解析するカスタムセルパーサ書くことができます。

customCell :: Parser Int 
customCell = read <$> many1 digit 

をしてCSVファイルを解析:

> parse (csv customCell) "" "1,2,3\n4,5,6\n" 
Right [[1,2,3],[4,5,6]] 
> 

ここでは、コンマ区切りのセルを明示的に解析して別のパーサーに送る文字列に変換するサブパラーを代わりに使用する代わりに、「セル」は暗黙のコンテキスト入力されたストリームの途中の行の途中でコンマで区切られたセルが必要となる適切なポイントで、基礎となる入力ストリームを解析するために呼び出されます。

関連する問題