Der Kommentar von @amalloy, dass Listen-Comprehensions auf eine "lokale" Perspektive beschränkt sind, ist der Schlüssel Einblick hier. Es gibt eine vernünftige Möglichkeit, nub
als Listenverständnis zu schreiben, aber Sie müssen zuerst Ihre Perspektive ändern.
Eine oft nützliche Funktion, die leider aus der Bibliothek weggelassen wurde, ist die Funktion, die jedes Element einer Liste mit seinem Kontext schmückt.
picks :: [x] -> [([x], x, [x])]
picks [] = []
picks (x : xs) = ([], x, xs) : [(x : bs, y, as) | (bs, y, as) <- picks xs]
So
picks [1,2,3] =
[([],1,[2,3]), ([1],2,[3]), ([1,2],3,[])]
Jedes Element der Liste in der Mitte eines dreifachen gesetzt wird, mit den Elementen ‚vor‘ auf der linken und die Elemente ‚nach‘ auf der rechten Seite.
This answer of mine erklärt die tiefe Struktur, die picks
in gewissem Sinne eine "Standard" -Operation macht, abgeleitet von der Struktur von Listen. Aber wir benötigen diese Hintergrundinformationen nicht, um sie zu implementieren.
Die picks
Funktion gibt uns genau die kontextuellen Informationen, die wir nub
als Listenverständnis schreiben müssen. Alles, was wir tun müssen, ist die Elemente auszuwählen, die nicht in ihren eigenen "Vorher-Listen" vorkommen.
myNub :: Eq x => [x] -> [x]
myNub xs = [x | (bs, x, as) <- picks xs, not (elem x bs)]
Ich mache keine Versprechungen in Bezug auf die Effizienz dieser Operation, aber ich mag die Klarheit, die sich aus der Kombination Listenkomprehensionen mit zusätzlichen räumlichen Kontext kommt.
Tun Sie das nicht mit einem Listenverständnis, verwenden Sie einfach die "nub" -Funktion (https://hackage.haskell.org/package/base-4.10.0.0/docs/Data-List.html#v :Kern). Oder, möglicherweise noch besser, abhängig von Ihrem Anwendungsfall, verwenden Sie einen ['Set'] (https://hackage.haskell.org/package/containers-0.5.10.2/docs/Data-Set.html#t:Set) anstelle einer Liste. –
Ja, aber ich versuche es zu üben und zu lösen, ohne eingebaute Funktionen. – MandyLB
Dies ist nicht möglich mit nur Schutzklauseln in einem Listenverständnis. Diese beschränken sich auf eine "lokale" Perspektive und betrachten jeweils nur ein Element. Um Elemente auszuschließen, die auf dem Rest der Eingabe basieren, benötigen Sie ein anderes Konstrukt, z. B. "Nub" oder eine Falte. – amalloy