Я бы написать
integer :: Parser Integer
integer = read <$ many1 space <*> many1 digit
Там куча левого ассоциативно (например, приложения) парсер-строительные операторы <$>
, <*>
, <$
, <*
. Вещью в крайнем левом углу должна быть чистая функция, которая собирает значение результата из значений компонента. Вещь справа от каждого оператора должна быть парсером, в совокупности предоставляющим компоненты грамматики слева направо. Какой оператор использовать, зависит от двух вариантов:
the thing to the right is signal/noise
_________________________
the thing to the left is \
+-------------------
pure/| <$> <$
a parser | <*> <*
Таким образом, избрав read :: String -> Integer
как чистая функция, которая собирается доставить семантику парсера, мы можем классифицировать ведущее место как «шум» и кучей цифр, как «сигнал», следовательно,
read <$ many1 space <*> many1 digit
(..) (.........) (.........)
pure noise parser |
(.................) |
parser signal parser
(.................................)
parser
Вы можете объединить несколько возможностей с
p1 <|> ... <|> pn
и выражают невозможность с
empty
Редко необходимо назвать компоненты в синтаксических анализаторах, а полученный код больше похож на грамматику с добавленной семантикой.
Почему 'const'? – MathematicalOrchid
Мы хотим игнорировать значение (но не эффект) 'many1 space' и применять' read' к значению 'many1 digit'. (Извините, я только что пришел, уже поздно, я устал: я играю быстро и свободно с терминологией.) Если вы представляете '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' many1 digit' соответственно, тогда значение (игнорируя эффекты) 'const read <$> many1 space <*> many1 digit' is' const read sd' = 'read d'. – dave4420