2016-02-06 5 views
7

Ich gehe durch die learn you a haskell Tutorial und Ich stolperte über einige der Beispiele, die der Autor gegeben hat.Haskell Pattern Matching: Lesbarkeit und Leistung

Zum Beispiel er reimplementiert zip wie folgt:

zip' :: [a] -> [b] -> [(a,b)] 
zip' _ [] = [] 
zip' [] _ = [] 
zip' (x:xs) (y:ys) = (x,y):zip' xs ys 

Er verwendet einen ähnlichen Ansatz für all seine anderen Beispielen , wo er zuerst die meisten spezifischen Mustern setzt. Hier ist eine etwas andere Version der Zip-Funktion:

zip' :: [a] -> [b] -> [(a,b)] 
zip' (x:xs) (y:ys) = (x, y):zip' xs ys 
zip' _ _   = [] 

Soweit ich verstehe beiden Methoden das gleiche tun. Wenn eine leere Liste entweder Weg (x: xs) oder (y: ys) wird nicht übereinstimmen, die die Rekursion durch Anhängen die leere Liste [] abgeschlossen wird.

  1. Ich persönlich bevorzuge die zweite Version für die Lesbarkeit, aber vielleicht liege ich falsch damit.
  2. Hat es Auswirkungen auf die Leistung einer Methode? Soweit ich weiß, wenn das oberste Muster nicht übereinstimmt, wird Haskell gegen das nächste Muster prüfen. Beeinflusst die Reihenfolge der Muster die Leistung?

Mit freundlichen Grüßen

Edit:

Möglicherweise Duplikat von: Haskell GHC: what is the time complexity of a pattern match with N constructors?

Zusammenfassung: Die Reihenfolge der Muster für die Semantik sehr wichtig ist (im Hinblick auf die strenge Bewertung der Argumente) und die Lesbarkeit einer Funktion. Die Musterübereinstimmung selbst wird immer in O (1) Zeitkomplexität sein.

+0

Mögliches Duplikat von [Haskell GHC: Wie hoch ist die zeitliche Komplexität einer Musterübereinstimmung mit N Konstruktoren?] (Http://stackoverflow.com/questions/9027384/haskell-ghc-what-is-the-time-complexity -of-a-pattern-match-with-n-Konstruktoren) – Nimi

Antwort

7

Soweit ich verstehe, machen beide Methoden das gleiche.

fast; mit einer Ausnahme:

\> zip' undefined [] -- 1st definition of zip' 
[] 
\> zip' (filter (< 4) [1..]) [1, 2, 3] 
[(1,1),(2,2),(3,3)] 

während:

\> zip' undefined [] -- 2nd definition of zip' 
*** Exception: Prelude.undefined 
\> zip' (filter (< 4) [1..]) [1, 2, 3] 
[(1,1),(2,2),(3,3) -- gets stuck here; never returns 

mit anderen Worten, zwingt die zweite Definition immer weak head normal form für beiden Argumente.

Leistungsmäßig bedeutet dies, dass man ein pathologisches Beispiel so erstellen kann, dass WHNF schwere Berechnungen beinhaltet, deshalb eine Definition führt sehr anders als die andere aus.

+3

Das stimmt. Aber 'zip 'undefined [1, 2, 3]' erzeugt in beiden Fällen eine Ausnahme. Ich kann also nicht sehen, wie das hilft oder warum es wünschenswert wäre. – Nimi

+1

@Nimi, in diesem Fall bestimmt es nur * das * Argument ist unbedingt streng. – dfeuer

+1

@Nimi der Punkt war, dass Sie die beiden Funktionen sich sehr unterschiedlich verhalten können und nicht das Gleiche tun können. Beachten Sie das andere Beispiel, 'zip '(Filter (<4) [1 ..]) [1, 2, 3]', um zu sehen, wie dies auch die Leistung beeinflussen kann. –