compréhension attoparsec
-
01-10-2019 - |
Question
attoparsec a été suggéré de me pour analyser un fichier, maintenant je dois comprendre comment l'utiliser; quelqu'un m'a donné ce morceau de code:
#
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)
qui fonctionne très bien, mais je ne sais pas pourquoi: la raison de l'utilisation de feuilles mobiles, est-il pas plus facile de mettre l'argument de A.feed dans un ordre différent? et pourquoi est-il B.empty? est-il un tutoriel sur que je peux étudier? merci à l'avance
La solution
Il y a une explication de la nécessité de feed
dans les réponses à cette question StackOverflow . Comme Bryan O'Sullivan (le créateur de Attoparsec) dit là:
Si vous écrivez un analyseur attoparsec que consomme le plus d'information possible avant d'échouer, vous devez indiquer au continuation de résultat partiel lorsque vous avez atteint la fin de votre entrée.
Vous pouvez le faire en nourrissant un bytestring vide.
Je dois admettre que j'ai écrit le code en question, et je fait ne pas utiliser pointfree
dans ce cas. Composition simple tout à fait logique pour moi ici: vous exécutez l'analyseur (A.parse environment
), vous lui dites que vous avez terminé (flip A.feed B.empty
), et vous convertir en Maybe
comme une sorte de gestion des erreurs de base (maybeResult
). À mon avis, ce se sent plus propre que la version pointue:
parseEnvironment b = maybeResult $ A.feed (A.parse environment b) B.empty
Le reste est je pense assez idiomatiques analyse syntaxique applicative, bien que Je ne sais pas pourquoi j'aurais utilisé >>
au lieu de *>
.