2015-02-26 3 views
7

Nachdem ich das Beispiel einer RPN calculator in "Lernen Sie eine Haskell für großes Gutes!" Ich wollte es auf eine allgemeinere Art und Weise neu schreiben.Wie schreibe ich diesen Case-Ausdruck mit der View-Pattern-Syntax?

Um die verfügbaren Funktionen einfach zu erweitern, lege ich diese in getrennte Listen und Muster, die mit der ViewPatterns Syntax der lookup Funktion übereinstimmen. Um die Eingabe mit read zu lesen schrieb ich folgendes:

parse xs x = case readMaybe x of 
    Just x -> Right (x : xs) 
    Nothing -> Left "Syntax error 

aber ich möchte lieber einen Fall Ausdruck vermeiden und verwenden Sie wieder die Ansicht Muster wie folgt aus:

parse xs (readMaybe -> Just x) = Right (x : xs) 
parse xs (readMaybe -> Nothing) = Left "Syntax error" 

jedoch mit diesem erhalte ich Dieser Fehler: No instance for (Read a0) arising from a use of ‘readMaybe’

Ich verstehe nicht warum. Sind sie nicht gleichwertig?

Der gesamte Code ist here.

Antwort

11

Sie sind nicht gleichwertig. Die case Version hat eine readMaybe, die View-Pattern-Version hat zwei. Für jeden readMaybe muss der Compiler ableiten, welcher Typ das Ziel des Leseversuchs ist. Wenn der Code sagt

parse xs x = case readMaybe x of 
    Just x -> Right (x : xs) 
    Nothing -> Left "Syntax error 

der Detektiv GHC bemerkt, dass in Ihrem Just x Fall x endet Consed zu xs, und so müssen nehmen, was Art der Elemente xs haben. Und das ist gute Arbeit.

Aber wenn man

schreiben
parse xs (readMaybe -> Just x) = Right (x : xs) 
parse xs (readMaybe -> Nothing) = Left "Syntax error" 

Sie erstellen zwei separate find-the-Ziel-Typ Probleme, eine für jede Verwendung von readMaybe. Die erste davon wird in genau der gleichen Weise wie im case Fall gelöst, aber für die zweite, einzeln zu lesen,

parse xs (readMaybe -> Nothing) = Left "Syntax error" 

gibt es einfach keine Ahnung was es ist, dass Sie lesen versagen, und kein Grund zu glauben, dass es dasselbe ist wie in der obigen Zeile.

Im Allgemeinen ist es nicht angemessen, Ansichtsmuster zu verwenden, es sei denn, es gibt nur ein Ergebnis von Interesse. Sie sind die falsche Syntax, wenn Sie eine Zwischenberechnung einmal durchführen möchten, aber das Ergebnis in mehr als einem Fall analysieren. Ich bin glücklich darüber, dass ich aus diesem Grund ein Fehlverhalten sehe.

+0

Ok, danke. Ich werde den Fall behalten. – Rnhmjoj

+0

View-Muster sind sehr nützlich, wenn Sie eine Funktion mit vielen Fällen haben, aber die Fälle sind mit Funktionen gemacht, die ein Maybe zurückgeben, und Sie passen nie wirklich auf den Zwischentyp. Dinge wie 'f x | Nur y <- g0 x = ...; Nur y <- g1 x = ... 'gegen' f (g0 -> Nur y); f (g0 -> Just y) '- Letzteres ist viel schöner, weil es keine nutzlose Variable bindet (' x' im ersten Fall). – user2407038

+1

Es lohnt sich, Pattern Matching zu unterstützen, das Zwischenberechnungen verwendet. Das Problem ist, dass Ansichtsmuster nur diesem Just-or-Bust-Stil gute Unterstützung bieten. Wir sollten mehr als einen Biss am Ergebnis einer Zwischenuntersuchung haben können, ohne die linke Seite verlassen zu müssen.Aber ich stimme zu, dass unnötige zusätzliche Benennung nervig ist, also könnte es nützlich sein, eine kompaktere Notation zu haben (wenn die Zwischenberechnung nur von einer Mustervariable abhängt und einmal gematcht wird) und ich will auch nichtlineare Muster anstelle eines zusätzlichen Namens und Gleichheitswächter. – pigworker

Verwandte Themen