Haskell: FRP Reactive Parsec?
Есть ли (или возможно ли) реактивный Parsec
(или любой другой чистый функциональный парсер) в Haskell?
Проще говоря, я хочу кормить парсер самостоятельно char от char и получать результаты столько, сколько я достаточно кормлю для получения результата.
Или намного проще, как я могу это сделать в foldr
или по крайней мере map
?
Нужна ли нам другая версия для поддержки такого реактивного поведения?
ИЗМЕНИТЬ
Мой вопрос касается, в частности, FRP. Я использовал синтаксический анализатор в качестве примера, и это было лучшее, что я мог придумать, чтобы прояснить мой вопрос и дать большую картину того, что мне нужно.
Я считаю, что FRP - это не только пользовательский интерфейс, верно?
Ответы
Ответ 1
Вы не можете проводить онлайн-парсинг в Parsec, он должен использовать все входные данные, чтобы определить, существует ли действительный синтаксический анализ или нет.
Однако есть альтернативы.
Одна из возможностей - использовать комбайны Компиляторы анализатора Утрехта, он имеет онлайн-парсинг среди своих функций.
Ответ 2
Я не считаю правильным называть это "FRP", правильное название для этого типа онлайн-алгоритм, что означает, что парсер производит вывод, как только он получает вход. (В отличие от автономного алгоритма, где парсер получает весь входной фронт и производит вывод из этого.)
В Haskell ленивая оценка позволяет легко писать онлайн-алгоритмы. Malcom Уоллес разработал специальный набор комбинаторов парсеров для онлайн-анализа, которые используют ленивую оценку.
Ответ 3
Вы можете делать онлайн-парсинг в Parsec, но для этого вам нужно сложить его поверх чего-то вроде iteratee.
Parsec 3 способен работать с произвольными типами Stream, поэтому вы можете создать экземпляр Stream, который рассматривает текущий "поток" как позицию и использует итерацию для извлечения значения в этой позиции.
Одним из таких примеров является пакет iteratee-parsec.
Другой подход представлен синтаксический анализ trifecta talk on iteratees и parsec (предупреждение PDF):
Компромисс заключается в создании типа, подобного итерации, который буферизует последние несколько фрагментов фрагментов, а не все из них, чтобы позволить ему сохранять ограниченное использование пространства и полагаться на итерационное оборудование для обратного отслеживания. Это то, что я сейчас использую, но у меня нет никакого кода для него.
Как только у вас есть инвертированное управление, запустив Parsec поверх Iteratee, довольно легко подать его на ввод персонажа за раз и посмотреть, удалось ли ему еще что-нибудь распознать.
Ответ 4
Взгляните на attoparsec-канал, с правильным парсером, это может быть полезным способом перевода потока байтов в поток анализируемых структур данных.