How to define a rotates function that generates all rotations of the given list?
For example: rotates [1,2,3,4] =[[1,2,3,4],[2,3,4,1],[3,4,1,2],[4,1,2,3]]
The answers given so far work fine for finite lists, but will eventually error out when given an infinite list. (They all call length
on the list.)
shift :: [a] -> [a]
shift xs = drop 1 xs ++ take 1 xs
rotations :: [a] -> [[a]]
rotations xs = zipWith const (iterate shift xs) xs
My solution uses zipWith const
instead. zipWith const foos bars
might appear at first glance to be identical to foos
(recall that const x y = x
). But the list returned from zipWith
terminates when either of the input lists terminates.
So when xs
is finite, the returned list is the same length as xs
, as we want; and when xs
is infinite, the returned list will not be truncated, so will be infinite, again as we want.
(In your particular application it may not make sense to try to rotate an infinite list. On the other hand, it might. I submit this answer for completeness only.)