Lassen Sie mich zunächst Ihre Funktion ein wenig umschreiben, als
isListOk :: Bool
isListOk = length (filter isItemOk [1 .. 1000]) <= 3
ist wohl mehr idiomatische als Ihre Version. (Beachten Sie, dass ich auch die Art Signatur geändert haben wie Sie falsch waren. Darüber hinaus sollten Sie 1 .. 1000
eher geschrieben haben, als 1.1000
.)
Verzögerte Auswertung ist dein bester Freund hier, wie es in der Regel dafür sorgen, dass keine unnötigen Berechnungen werden durchgeführt.
Leider ist Ihre Verwendung von length
(oder Zuordnung jedes Element aus einer Liste auf 1 und dann die resultierende Liste summieren, wie Sie) in den Weg kommt hier. Das heißt, length
ist streng in der Wirbelsäule der Liste: es kann nur die Länge der Liste produzieren, wenn es bis zu seinem Ende auswertet, was in diesem Fall bedeutet, dass Ihr Programm Ihren Scheck tausend Mal ausführen muss .
Eine Lösung wäre, die Berechnung der Länge zu kombinieren (d. H.Die Traversierung der Wirbelsäule in der Liste) und der Test, ob die berechnete Länge in der Tat nicht eine bestimmte Schwelle in eine einzige Funktion überschreiten, die in der Wirbelsäule der Argumentliste lazy ist:
isNotLongerThan :: [a] -> Integer -> Bool
isNotLongerThan [] n = n >= 0
isNotLongerThan (_ : xs) n = n >= 1 && isNotLongerThan xs (n - 1)
und dann schreiben
isListOk :: Bool
isListOk = filter isItemOk [1 .. 1000] `isNotLongerThan` 3
Für eine wiederverwendbare Lösung, Sie beide das Prädikat natürlich abstrakt über und der Schwelle:
forNoMoreThan :: (a -> Bool) -> Integer -> [a] -> Bool
forNoMoreThan p n = (`isNotLongerThan` n) . filter p
isListOk :: Bool
isListOk = (isItemOk `forNoMoreThan` 3) [1 .. 1000]
schließlich als hammar weist darauf hin, wenn Ihr dreschen alt ist klein genug und behoben, Sie können einfach Mustervergleich verwenden, um festzustellen, ob eine Liste kurz genug ist.
Ihre Funktion wird nicht über 4 hinausgehen, da "Take" und "Listenverständnis" faul sind. Versuchen Sie "Int" zu verwenden, wenn Sie wissen, dass Ihre Zahl nicht über das Limit hinaus wächst, da sie viel schneller ist als "Integer". Es ist 'Bool' und nicht' Boolean'. 'isListOk' sollte ein Listenargument enthalten. – Satvik