Понимание Text.ParserCombinators.ReadP.sepBy1 - PullRequest
1 голос
/ 10 марта 2019

Я смущен результатом sepBy1

Следующий код работает в ghci

λ> import Text.ParserCombinators.ReadP
λ> import Data.Char

λ> readP_to_S ((munch1 isAlpha) `sepBy1` (char '-')) "dish-dash-dosh"
[(["dish"],"-dash-dosh"),(["dish","dash"],"-dosh"),["dish","dash","dosh"],"")]

  1. Почему это не так, что вывод[(["dish","dash","dosh"],"")]?

Следующий doctest - это только один , который не удалось.

-- |
-- >>> readP_to_S readValues "dish-dash-dosh"
-- [(V ["dish","dash","dosh"],"")
readValues :: ReadP Value
readValues = do
  xs <- (munch isAlpha) `sepBy1` (char '-')
  pure $ V xs
Main.hs:64: failure in expression `readP_to_S readValues "dish-dash-dosh"'
expected: [(V ["dish","dash","dosh"],"")
 but got: [(V ["dish"],"-dash-dosh"),(V ["dish","dash"],"-dosh"),(V ["dish","dash","dosh"],"")]

Я использую ReadP для Read экземпляр моих данных.Код для Read экземпляра работает, но я в замешательстве.

Не было никакого сложного анализа, я всегда думаю, что выполнение ReadP вернет вывод в виде списка из одного элемента [(result,"")], очевидно, это не так.

data Value = V [String]
  deriving Show

-- |
-- >>> read "dish-dash-dosh" :: Value
-- V ["dish","dash","dosh"]
--
instance Read Value where
  readPrec = readP_to_Prec (const readValues)

Это тот случай, когда read будет успешным, только если в snd из последних [(Value,String)] ничего не осталось, другие элементы в этом списке нигде не используются?

IЯ знаю альтернативный способ сделать это.Этот вопрос касается только понимания sepBy вывода и его использования.

1 Ответ

3 голосов
/ 10 марта 2019

Запуск ReadP вернет все возможные синтаксические анализ.Вы можете ограничить количество допустимых разборов, указав, что должно произойти после разбора sepBy1, например, конец ввода или какой-либо другой синтаксический элемент.

Например, попробуйте что-то вроде:

readValues = do
  xs <- (munch isAlpha) `sepBy1` (char '-')
  eof
  pure $ V xs

Добавление ...

Тип ReadS следует развитию монадического синтаксического анализа, представленного в классической статье Хаттона и Мейера Монадический синтаксический анализ в Haskell .Из небольшой документации я понял, что ReadP осуществляет параллельное исследование всех альтернатив.Существует большая поддержка для создания ReadP действий и не так много для ReadS, поэтому я думаю, что вы используете библиотеку правильно, создав действие ReadP и затем используя readP_to_S в конце.Когда я использовал модуль, я только что взял первое совпадение действия ReadS (или вернул ошибку синтаксического анализа, если это был пустой список).

Монада ReadPrec используется для поддержкиприоритет, и это в основном ReaderT Int ReadP - здесь Int является текущим приоритетом.Опять же, похоже, что вы начинаете с парсера ReadP, а затем конвертируете его в действие ReadPrec, используя lift или readP_to_Prec.Для запуска вы можете использовать readPrec_to_S, как в случае ReadP.

...