質問
Attoparsecはファイルを解析するために私に提案されましたが、今ではそれを使用する方法を理解する必要があります。誰かが私にこのコードをくれました:
#
type Environment = M.Map String String
import Data.Attoparsec (maybeResult)
import qualified Data.Attoparsec.Char8 as A
import qualified Data.ByteString.Char8 as B
environment :: A.Parser Environment
environment = M.fromList <$> A.sepBy entry A.endOfLine
parseEnvironment = maybeResult .flip A.feed B.empty . A.parse environment
spaces = A.many $ A.char ' '
entry = (,) <$> upTo ':' <*> upTo ';'
upTo delimiter = B.unpack <$> A.takeWhile (A.notInClass $ delimiter : " ")
<* (spaces >> A.char delimiter >> spaces)
それは非常にうまく機能しますが、理由はわかりません。フリップを使用する理由は何ですか。そして、なぜb.emptyがあるのですか?勉強できるというチュートリアルはありますか?前もって感謝します
解決
必要性の説明があります feed
の答えで このスタックフローの質問. 。 Bryan O'Sullivan(Attoparsecの作成者)が言うように:
故障する前にできるだけ多くの入力を消費するattoparsecパーサーを書く場合は、入力の終了に到達したときに部分的な結果の継続を伝える必要があります。
これを行うことができます。これは、空のバイテストリングを提供することで行うことができます。
問題のコードを書いたことを認めますが、実際には使用しませんでした pointfree
この場合。ここではシンプルな構成が私には理にかなっています:あなたはパーサーを実行します(A.parse environment
)、あなたはそれが完了したと言います(flip A.feed B.empty
)、そしてあなたはaに変換します Maybe
一種の基本的なエラー処理として(maybeResult
)。私の意見では、これは尖ったバージョンよりもきれいに感じます:
parseEnvironment b = maybeResult $ A.feed (A.parse environment b) B.empty
残りはかなり慣用的だと思います アプリケーション解析, 、なぜ私が使用したのかわかりませんが >>
それ以外の *>
.
所属していません StackOverflow