Понимание ATTOPARSEC.
-
01-10-2019 - |
Вопрос
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)
Это очень хорошо работает, но я не знаю почему: какова причин использования флип, не проще поставить аргумент A.FEED в другом порядке? И почему там б. Пусты? Есть ли урок о том, что я могу учиться? заранее спасибо
Решение
Есть объяснение необходимости в feed
в ответах на Этот вопрос стойки. Отказ Как Брайан О'Салливан (Создатель Attoparsec) говорит там:
Если вы пишете анализатор ATTOPARSEC, который поглощает как можно больше ввода до того, как вы не удалитесь, вы должны сообщить о продолжении частичного результата, когда вы достигли конца вашего ввода.
Вы можете сделать это, кормив его пустым бассейном.
Я признаю, что написал под вопросом код, и я на самом деле не использовал pointfree
в этом случае. Простая композиция просто имеет смысл для меня здесь: Вы бегаете парсер (A.parse environment
), вы говорите, что вы сделали (flip A.feed B.empty
), а вы преобразуете в Maybe
как вид базовой обработки ошибок (maybeResult
). На мой взгляд, это чувствует себя более чистым, чем указанная версия:
parseEnvironment b = maybeResult $ A.feed (A.parse environment b) B.empty
Остальные я думаю, что довольно идиоматично Применительный разбор, хотя я не уверен, почему я бы использовал >>
вместо *>
.