parser rzeczy
jest funkcją z ciągów
do listy par
rzeczy i ciągi!
- Różne źródła
To pomaga w rozumowaniu o programach myśleć o abstrakcji pod względem ich intencji, zamiast ich realizacji. Tak więc, podczas gdy type ReadS a = String -> [(a, String)]
, jest to drugorzędne względem faktycznego celu analizowania rzeczy i łączenia analizatorów składni ReadS
. Jak Rhymoid zaznacza:
composeReads :: ReadS a -> ReadS b -> ReadS (a,b)
oddaje intencję składzie parsera, jak i szczęśliwym skutkiem ubocznym jest o wiele bardziej zwięzłe, niż inlined równoważne:
composeReads
:: (String -> [(a, String)])
-> (String -> [(b, String)])
-> (String -> [((a, b), String)])
To dobry i oczywistą rzeczą czynnik poza tym powtórzeniem, nie tylko dlatego, że dobrze jest unikać powtarzania, ale także zwiększać w miarę możliwości ilość użytecznej treści semantycznej w linii. A jeśli chcemy zmienić sposób implementacji tych parserów, umieszczenie ich za tym aliasem to mały krok, który może pozwolić nam uniknąć ogromnych zmian w każdej pojedynczej witrynie użytkowania.
Widać to wielokrotnie w różnych kombinatorach bibliotek parsera, takich jak Parsec, Attoparsec i uu-parsinglib. A Parser
to Parser
, a im bardziej te czarne pudełka są takie, tym łatwiej jest je odtwarzać oddzielnie.
Czytelność, w zasadzie. Nadanie koncepcji nazwy ułatwia myślenie i rozmowę. – MathematicalOrchid
Jako przykład: 'composeReads :: ReadS a -> ReadS b -> ReadS (a, b)' jest bardziej czytelny niż 'composeReads :: (String -> [(a, String)]) -> (String -> [(b, String)]) -> (String -> [((a, b), String)]) '. –