It is necessary to implement the function that sets the cyclic rotation of the list. If the integer argument is positive, the rotation should be to the left, and negative, to the right.

Prelude> rotate 2 "abcdefghik" "cdefghikab" Prelude> rotate (-2) "abcdefghik" "ikabcdefgh" 

You also need to ensure the performance on endless lists (for scenarios when it makes sense) and reasonable efficiency with a large number of rotations of a small list:

 Prelude> :set +s Prelude> rotate 1234567890 [1..10] [1,2,3,4,5,6,7,8,9,10] (0.00 secs, 0 bytes) 

I made this decision:

 rotate :: Int -> [a] -> [a] rotate _ [] = [] rotate 0 xs = xs rotate n xs = bs ++ as where (as, bs) = splitAt (n `mod` length xs) xs 

But unfortunately it is not effective:

 Failed test #1. Run time error: main: out of memory (requested 1048576 bytes) 

What can there be an effective solution?

  • 2
    Your decision leads to the calculation of the entire list because of the length function. On endless lists it, alas, will not work. - Alexander Razorenov

1 answer 1

 rotate :: Int -> [a] -> [a] rotate _ [] = [] rotate _ xs@[x] = xs rotate 0 xs = xs rotate n xs'@(x:xs) | n > 0 = rotate (n-1) (xs ++ [x]) | n < 0 = rotate (n+1) (last xs' : init xs') 

As for the infinite lists: there is no possibility of checking the list for an infinite, so the infinite or not the list should be determined by the programmer, respectively, the function of rotating the infinite list is reduced only to discarding the left element and going to the next, i.e. there can be no negative rotation, and the problem of rotating an infinite list itself is not correct, in my opinion.