TL&DR
rotate :: Int -> [a] -> [a]
rotate = drop <> take
In Haskell the most concise but also a curious way to rotate a list could be using the Semigroup type class instance of the function type (a -> b). Lets check the relevant part of the instance.
instance Semigroup b => Semigroup (a -> b) where
f <> g = \x -> f x <> g x
First things first, <> is in fact the inline version of the mappend function from the Monoid type class.
Then we see, the Semigroup b => constraint in the type signature states that the return type b should also be a member of Semigroup type class. Since we use drop :: Int -> [a] -> [a] and take :: Int -> [a] -> [a] we can quickly notice that b is in fact another function with type signature [a] -> [a] so it is a member of Semigroup type class if and only if it's b, which happens to be [a] is also a member of the Semigroup type class and it is.
instance Semigroup [a] where
(<>) = (++)
So everything holds so far but how does it work?
We can deduce from the type signatures as follows;
(drop :: Int -> ([a] -> [a])) <> (take :: Int -> ([a] -> [a])) is
\n -> (drop n :: [a] -> [a]) <> (take n :: [a] -> [a]) which is
\n -> \xs -> (drop n xs :: [a]) <> (take n xs :: [a]) which is
\n -> \xs -> (drop n xs) ++ (take n xs)
This is basically better than the answers using recursive ++ operator to add the head as a singleton list to the end of the tail since it yields an O(n^2) time complexity.