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-канал, с правильным парсером, это может быть полезным способом перевода потока байтов в поток анализируемых структур данных.