Вопрос нуба по Haskell.
Я весело провел время, написав несколько парсеров как с Parsec, так и с AttoParsec. Теперь я хочу собрать информацию в процессе синтаксического анализа (по сути, построить таблицу символов), и использование преобразователя монад WriterT кажется хорошим вариантом.
У меня это работает сейчас в этом простом примере:
module NewParse where
import qualified Text.ParserCombinators.Parsec as A
import Control.Monad.Trans (lift)
import Control.Monad.Writer (WriterT, tell, runWriterT)
type WParser a = WriterT [String] A.Parser a
data StoryToken = StoryToken Char deriving (Show)
getToken :: WParser StoryToken
getToken = do
tell ["hello from Writer T"]
c <- lift A.anyChar
return $ StoryToken c
test = A.parse (runWriterT getToken) "story" "#"
Это прекрасно работает. Вызов теста в ghci дает мне это:
*NewParse> test
Right (StoryToken '#',["hello"])
Чего я немного опасаюсь, применяя это к моему коду синтаксического анализатора, чтобы поднимать монаду синтаксического анализатора для каждого каждого его вызова. Я буду вызывать Tell относительно нечасто, но парсер работает много. Код станет намного уродливее.
Есть ли способ легко раскрыть определенные функции из Parsec, чтобы мне не приходилось использовать подъем в коде?
Решение, которое сработало для меня, заключалось в создании моей собственной функции
anyChar = lift A.anyChar
Это круто, но потребовало бы создания подобных теневых функций для каждой функции, которую я использую из parsec.
И я не возражаю против этого, но просто подумал, есть ли лучший, менее шаблонный способ добиться того же самого.
Любая помощь с благодарностью принята :)