bym napisać
integer :: Parser Integer
integer = read <$ many1 space <*> many1 digit
Jest grono wiązanie lewe (jak aplikacji) Operatorzy parser-budowlanych <$>
, <*>
, <$
, <*
. Rzecz po lewej stronie powinna być czystą funkcją, która składa wartość wyniku z wartości składowych. Rzecz po prawej stronie każdego operatora powinna być parserem, zbiorowo podając elementy gramatyki od lewej do prawej. Wybór operatora zależy od dwóch opcji, jak następuje.
the thing to the right is signal/noise
_________________________
the thing to the left is \
+-------------------
pure/| <$> <$
a parser | <*> <*
Tak, wybrawszy read :: String -> Integer
jako czystej funkcji, która ma zamiar dostarczyć semantykę parsera, możemy sklasyfikować główną przestrzeń jako „szum”, a bandą cyfr jako „sygnał”, stąd
read <$ many1 space <*> many1 digit
(..) (.........) (.........)
pure noise parser |
(.................) |
parser signal parser
(.................................)
parser
można łączyć wiele możliwości z
p1 <|> ... <|> pn
i wyraźnej niemożności z
empty
Rzadko trzeba nazwać komponenty w analizatorach składni, a wynikowy kod wygląda bardziej jak gramatyka z dodaną semantyką.
Dlaczego "const"? – MathematicalOrchid
Chcemy zignorować wartość (ale nie efekt) 'many1 space' i zastosować' read' do wartości 'wiele1 cyfr'. (Przepraszam, właśnie wszedłem, jest późno, jestem zmęczony: gram szybko i luźno z terminologią.) Jeśli sobie wyobrazisz, że 's' i' d' reprezentują wartości 'many1 space' i' many1 digit', następnie wartość (ignorowanie efektów) 'const read <$> many1 space <*> many1 digit' to' const read sd' = 'read d'. – dave4420