2016-04-14 11 views
5

sagen, ich will die Länge Funktion für Listen mit Mustervergleich implementieren, dann könnte ich so etwas tun:Wie wird ein leerer Vektor in Haskell gemustert?

length' :: (Num b) => [a] -> b 
length' [] = 0 
length' (_:xs) = 1 + length' xs 

Kann ich etwas tun, ähnlich mit Vector s?

+3

Sie können Dinge wie 'ViewPatterns' und' PatternSynonyms' verwenden, um Muster auf abstrakte Typen anzupassen, aber wenn Sie eine induktive Funktion wie 'length' auf einen' Vector' schreiben möchten, warum nicht einfach 'foldl' verwenden 'oder' foldr' oder irgendeine der anderen Dutzend oder so Varianten von "falten", die "vector" bietet? Dies hat den Vorteil, zu jedem "faltbaren" zu verallgemeinern, wenn Sie z.B. 'Data.Foldable.foldr' anstelle der spezifischen Versionen in' vector'. – user2407038

+0

Vielleicht 'case splitAt 1 v von ...'? Möglicherweise in ein "ViewPattern", wie oben vorgeschlagen. – chi

+3

Vorsicht mit Mustersynonymen; Sie können Performance-Intuition brechen, wenn sie nicht gut entwickelt sind. – dfeuer

Antwort

3

Die verschiedenen Typen vector der Bibliothek Vector sind undurchsichtige Typen, die ihre Datenkonstruktoren nicht verfügbar machen, und als solche können Sie keine Mustervergleiche für sie erstellen.

Es gibt Möglichkeiten, um dieses, wie ViewPatterns (als Kommentar von user2407038 erwähnt), aber Sie sicherlich tun nicht diese mit Vektoren verwenden möchten, weil Sie wahrscheinlich Wurf entfernt der Vorteil der Vektoren .

Das Highlight der vector Bibliothek ist, dass es auf der Grundlage von zwei Konzepten implementiert ist:

  1. Vektoren werden als feste Größe, zusammenhängende Speicherarrays, die als Single- viel besser Speicherlokalizität bieten materialisieren verknüpfte Listen oder Bäume;
  2. Eine große Anzahl von Vektoroperationen sind in Bezug auf Schmelzströme implementiert, deren Operationen auf Schleifen kompilieren, die keinen Speicher für Zwischenvektoren zuweisen.

(1) bedeutet, dass ein Vektor nicht einen natürlichen „Kopf“ hat und „tail“ wie Listen do-Listen sind buchstäblich ein Paar aus einem Kopf und einen Schwanz. Wenn Sie eine Art Ansichtsmuster verwenden würden, um eine Kopf- und Schweifstruktur über einem Vektor anzuordnen, würden Sie effektiv eine einfach verknüpfte Liste der Vektorelemente erstellen, die wahrscheinlich die Speicherzuweisung für jeden Knoten des Vektors auslösen würde Ansichtstyp

Und wenn Sie ViewPatterns verwenden, um einen Vektor als was ist eigentlich eine einzelne verknüpfte Liste anzuzeigen, warum nicht einfach den Vektor in eine Liste konvertieren?

In jedem Fall, wegen der oben genannten Design-Punkte, mit vector wollen Sie wirklich so viel wie möglich zu the operations provided by the library itself Stick, weil sie die Leistungsmerkmale der Bibliothek ausnutzen.

Ich vermute, dass es eine gute Chance gibt, dass das Testen der Größe eines Vektors in vielen Kontexten eine suboptimale Idee sein könnte. Zum Beispiel in Code wie folgt:

example :: Vector something -> Vector somethingElse 
example as 
    | Vector.null as = ... 
    | otherwise  = ... 

... Ich würde erwarten (aber noch nicht überprüft!), Dass dies der Vektor as so materialisiert werden zwingen würde, dass wir prüfen, ob es leer ist oder nicht, wo Wenn der Test entfernt oder an anderer Stelle verschoben werden könnte, könnten die Operationen im Bit "..." mit dem Kontext verknüpft werden, in dem example verwendet wird.

+1

'Vector.empty :: Vector a' gibt tatsächlich einen leeren Vektor zurück. Sie würden stattdessen "Vector.null :: Vector a -> Bool" verwenden. –

+1

@JanGerlinger: Hoppla! Guter Fang, wurde behoben ... –

Verwandte Themen