3

I want to write a function in Haskell that rotates the list given as the second argument by the number of positions indicated by the first argument. Using pattern matching, implement a recursive function

I have written the following function:

rotate :: Int -> [a] -> [a]
rotate 0 [y]= [y]
rotate x [y]= rotate((x-1) [tail [y] ++ head [y]])

but this function always produces a error. Is there any way to solve it? The function should do the following when it runs:

rotate 1 "abcdef"
"bcdefa"
2
  • 5
    Please do not vandalize your posts. If you believe your question is not useful or is no longer useful, it should be deleted instead of editing out all of the data that actually makes it a question. By posting on the Stack Exchange network, you've granted a non-revocable right for SE to distribute that content (under the CC BY-SA 3.0 license). By SE policy, any vandalism will be reverted. Commented Sep 27, 2018 at 7:19
  • You can't easily delete a question which has upvoted answers, though. Commented Sep 27, 2018 at 7:26

3 Answers 3

6

[y] does not mean "let y be a list". It means "this argument is a list containing one element called y". You have the right structure, but you don't need the brackets around the y.

rotate :: Int -> [a] -> [a]
rotate 0 y = y
rotate x y = rotate (x-1) (tail y ++ [head y])
Sign up to request clarification or add additional context in comments.

2 Comments

Good answer, however, I think that mentioning pattern matching vs partial functions (head, tail) might be a good addition.
obligatory dv for the top voted answer with needlessly partial solution. sry.
2

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.

1 Comment

not to mention it being non-partial, unlike those other solutions. :)
1

I think you want something like this:

rotate :: Int -> [a] -> [a]
rotate 0 x = x
rotate times (x:xs) = rotate (times - 1) (xs ++ [x])

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.