Frage

Ich versuche, das Verhalten der Bibliotheksfunktion groupBy (von Data.List), um herauszufinden, die von einer „Gleichheitstest“ -Funktion übergeben als erstes Argument für Gruppenelemente einer Liste vorgibt. Die Art Signatur legt nahe, dass der Gleichheitstest muss nur Typen hat

(a -> a -> Bool)

Allerdings, wenn ich (<) als die "Gleichheitstest" verwenden in GHCi 6.6, sind die Ergebnisse nicht, was ich erwarten:

ghci> groupBy (<) [1, 2, 3, 2, 4, 1, 5, 9]
[[1,2,3,2,4],[1,5,9]]

Stattdessen würde ich läuft streng immer mehr erwarten, wie folgt aus:

[[1,2,3],[2,4],[1,5,9]]

Was bin ich fehlt?

War es hilfreich?

Lösung

Haben Sie einen Blick auf die ghc Implementierung von groupBy :

groupBy                 :: (a -> a -> Bool) -> [a] -> [[a]]
groupBy _  []           =  []
groupBy eq (x:xs)       =  (x:ys) : groupBy eq zs
                           where (ys,zs) = span (eq x) xs

Jetzt vergleichen diese zwei Ausgänge:

Prelude List> groupBy (<) [1, 2, 3, 2, 4, 1, 5, 9]
[[1,2,3,2,4],[1,5,9]]
Prelude List> groupBy (<) [8, 2, 3, 2, 4, 1, 5, 9]
[[8],[2,3],[2,4],[1,5,9]]

Kurz gesagt, was passiert, ist dies: groupBy geht davon aus, dass die gegebene Funktion (das erste Argument) Tests für die Gleichstellung und damit geht davon aus, dass die Vergleichsfunktion ist reflexive transitiv und symmetrisch (siehe ¨Aquivalenzrelation ). Das Problem hierbei ist, dass die weniger als Beziehung ist nicht reflexiv, noch symmetrisch ist.


Bearbeiten : Die folgende Implementierung nur davon ausgegangen, Transitivität:

groupBy' :: (a -> a -> Bool) -> [a] -> [[a]]
groupBy' _   []                        = []
groupBy' _   [x]                       = [[x]]
groupBy' cmp (x:xs@(x':_)) | cmp x x'  = (x:y):ys
                           | otherwise = [x]:r
  where r@(y:ys) = groupBy' cmp xs

Andere Tipps

Die Tatsache, dass "<" ist kein Gleichheitstest.

Sie können ein bestimmtes Verhalten erwarten, weil Sie es anders implementieren würde, aber das ist nicht das, was es verspricht.

Ein Beispiel dafür, warum, was es gibt eine vernünftige Antwort ist, wenn es durch sie fegt, macht

[1, 2, 3, 2, 4, 1, 5, 9] ->
[[1,2,3], [2,4], [1,5,9]]

hat nun drei Gruppen von gleichen Elementen. So prüft sie, ob einer von ihnen in der Tat ist die gleiche:

Da alle Elemente weiß in jeder Gruppe gleich ist, kann es auf dem ersten Elemente schaut nur in jeweils 1, 2 und 1.

1> 2? Ja! So verbindet er die ersten beiden Gruppen.

1> 1? Nein! So ist es die letzte Gruppe verlässt sein.

Und es ist jetzt alle Elemente auf Gleichheit verglichen.

... nur, du hast übergeben Sie es nicht die Art von Funktion erwartet.

Kurz gesagt, , wenn es einen Gleichheitstest will, geben es ein Gleichheitstest .

scroll top