Esiste una funzione integrata per ottenere tutte le sottosequenze consecutive di dimensione n di un elenco in Haskell?

Ad esempio, ho bisogno di una funzione:

gather :: Int -> [a] -> [[a]] gather n list = ??? 

dove gather 3 "Hello!" == ["Hel","ell","llo","ol!"] gather 3 "Hello!" == ["Hel","ell","llo","ol!"] .

Ho un’implementazione funzionante:

 gather :: Int-> [a] -> [[a]] gather n list = unfoldr (\x -> if fst x + n > length (snd x) then Nothing else Just (take n (drop (fst x) (snd x)), (fst x + 1, snd x))) (0, list) 

ma mi chiedo se c’è qualcosa già incorporato nella lingua per questo? Ho scansionato DataList ma non ho visto nulla.

Potresti usare le tails :

 gather nl = filter ((== n) . length) $ map (take n) $ tails l 

o usando takeWhile anziché filter :

 gather nl = takeWhile ((== n) . length) $ map (take n) $ tails l 

MODIFICA: puoi rimuovere il passaggio del filtro facendo cadere gli ultimi n elementi della lista restituita dalle tails come suggerito nei commenti:

 gather n = map (take n) . dropLast n . tails where dropLast n xs = zipWith const xs (drop n xs) 

La caduta delle code può essere organizzata per automagicamente, grazie alle proprietà di zipping ,

 import Data.List (tails) g :: Int -> [a] -> [[a]] gn = foldr (zipWith (:)) (repeat []) . take n . tails 

oppure una semplice transpose . take n . tails transpose . take n . tails transpose . take n . tails sarebbero sufficienti. test:

Dati prelettura.Lista> g 3 [1..10]
[[1,2,3], [2,3,4], [3,4,5], [4,5,6], [5,6,7], [6,7,8], [ 7,8,9], [8,9,10]]
Prelude Data.List> transpose. prendere 3. croce $ [1..10]
[[1,2,3], [2,3,4], [3,4,5], [4,5,6], [5,6,7], [6,7,8], [ 7,8,9], [8,9,10], [9,10], [10]]