Permettetemi innanzitutto di riscrivere la funzione di un po ', come
isListOk :: Bool
isListOk = length (filter isItemOk [1 .. 1000]) <= 3
è forse più idiomatica che la vostra versione. (Si noti che ho anche cambiato la firma tipo come il vostro è stato corretto. Inoltre, si dovrebbe avere scritto 1 .. 1000
piuttosto che 1.1000
.)
valutazione pigro è il tuo migliore amico qui, come in genere assicurarsi che nessun calcoli inutili saranno eseguita.
Sfortunatamente, l'utilizzo di length
(o il mapping di ciascun elemento da un elenco a 1 e quindi la somma dell'elenco risultante, come si fa) sta entrando in questo modo. Cioè, length
è rigoroso nella colonna vertebrale dell'elenco: può solo produrre la lunghezza dell'elenco se lo valuta fino alla sua fine, il che, in questo caso, significa che il tuo programma dovrà eseguire l'assegno migliaia di volte .
Una soluzione sarebbe quella di combinare il calcolo della lunghezza (ad es., L'attraversamento della colonna della lista) e il test se la lunghezza calcolata non supera una certa soglia in una singola funzione che è in realtà artificiale nella spina dorsale della sua lista di argomenti:
isNotLongerThan :: [a] -> Integer -> Bool
isNotLongerThan [] n = n >= 0
isNotLongerThan (_ : xs) n = n >= 1 && isNotLongerThan xs (n - 1)
e quindi scrivere
isListOk :: Bool
isListOk = filter isItemOk [1 .. 1000] `isNotLongerThan` 3
Per una soluzione riutilizzabile, è possibile ovviamente astratto su sia il predicato e la soglia:
forNoMoreThan :: (a -> Bool) -> Integer -> [a] -> Bool
forNoMoreThan p n = (`isNotLongerThan` n) . filter p
isListOk :: Bool
isListOk = (isItemOk `forNoMoreThan` 3) [1 .. 1000]
Infine, come sottolinea Hammar, se la vostra trebbiatura vecchio è abbastanza piccolo e fisso, si può semplicemente usare la corrispondenza del modello per determinare se un elenco è abbastanza corto.
La tua funzione non guarderà oltre 4 come 'take' e' list comprehension' sono pigri. Prova ad usare 'Int' se sai che il tuo numero non crescerà oltre il limite in quanto è molto più veloce di' Integer'. È 'Bool' e non' Boolean'. 'isListOk' dovrebbe prendere un argomento di lista. – Satvik