attoparsec comprensión
-
01-10-2019 - |
Pregunta
attoparsec me fue sugerido para analizar un archivo, ahora tengo que entender cómo usarlo; alguien me dio este pedazo de código:
#
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)
que funciona muy bien, pero no sé por qué: cuál es la razón de la utilización de la moneda, no es que sea más fácil de poner el argumento de A.feed en un orden diferente? y por qué hay B.empty? ¿hay algún tutorial sobre que puedo estudiar? gracias de antemano
Solución
Hay una explicación de la necesidad de feed
en las respuestas a esta pregunta Stackoverflow . Como Bryan O'Sullivan (el creador de Attoparsec) dice que:
Si usted escribe un programa de análisis que attoparsec consume tanta información posible antes de fallar, debe informar a la la continuación parcial resultado cuando has alcanzado el final de la entrada.
Se puede hacer esto por la alimentación de una cadena de bytes vacía.
voy a admitir que escribí el código en cuestión, y yo en realidad no utilizó pointfree
en este caso. Composición simple sólo tiene sentido para mí aquí: ejecutar el programa de análisis (A.parse environment
), le dice que ya está (flip A.feed B.empty
), y convertir a un Maybe
como una especie de control de errores básica (maybeResult
). En mi opinión esto se siente más limpio que la versión en punta:
parseEnvironment b = maybeResult $ A.feed (A.parse environment b) B.empty
El resto es bastante Creo idiomática aplicativo análisis , aunque no estoy seguro de por qué me gustaría tener >>
utiliza en lugar de *>
.