2013-08-11 12 views
5

Czytam kod źródłowy reads. reads jest zdefiniowany jako reads :: Read a => ReadS a Po prostu zwraca ReadS a, podczas gdy musi być instancją Read.Dlaczego haskell używa typu ReadS do reprezentowania funkcji?

I jest zdefiniowany jako type ReadS a = String -> [(a, String)], więc rzecz zwrócona z reads jest tylko funkcją, która pobiera ciąg znaków i zwraca tablicę krotki.

Wtedy zastanawiam się, dlaczego po prostu zdefiniuj reads bez ReadS a. Podobnie jak reads :: Read a => (String -> [(a, String)])

+6

Czytelność, w zasadzie. Nadanie koncepcji nazwy ułatwia myślenie i rozmowę. – MathematicalOrchid

+9

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)]) '. –

Odpowiedz

11

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.

+1

Dzięki za szczegółowe wyjaśnienie. zapamiętam to zdanie "Parser to parser to parser, a im bardziej czarne pole to są te rzeczy" :) – code4j

Powiązane problemy