Cilenco
Cilenco

Reputation: 7179

Haskell - Type error in application

I have a problem writing a Haskell function. The compiler says:

Type error in application

Expression : move (offset - 1) (saveList subList (x : xs)) xs

test :: Int -> [Int] -> [Int]
test _ [] = []
test offset (xs) = move offset [] xs
                   where
                       move offset subList (x:xs) | offset == 0 = subList ++ rotate (last (x:xs)) (x:xs)
                                                  | otherwise   = move (offset-1) (saveList subList (x:xs)) xs

                       saveList save (x:xs) = save ++ [x]

                       rotate _ [] = []
                       rotate item (x:xs) = item : (move x xs)
                
                       last (x:[]) = x
                       last (x:xs) = last xs

But I can't see any mistake. What did I do wrong?

Upvotes: 2

Views: 475

Answers (2)

svk
svk

Reputation: 5919

It looks like move is supposed to be a function of three arguments, but in rotate you use it like this: item : (move x xs).

In Haskell, move x xs is a valid value (it's the function obtained by currying move twice, first with x and then with xs), but it doesn't seem like what you want here.

When you get a confusing error message, it often helps to clarify what you mean to the compiler by adding type signatures. I added type signatures to your code like this:

move :: Int -> [Int] -> [Int] -> [Int]
saveList :: [Int] -> [Int] -> [Int]
rotate :: Int -> [Int] -> [Int]
last :: [Int] -> Int

GHCI then gives me the following error message, which is much more helpful about where the actual problem is:

foo.hs:14:52:
    Couldn't match expected type `[Int]'
           against inferred type `[Int] -> [Int]'
    In the second argument of `(:)', namely `(move x xs)'
    In the expression: item : (move x xs)
    In the definition of `rotate':
        rotate item (x : xs) = item : (move x xs)

This error message says quite plainly that when reading (move x xs) on line 14, GHCI expected to find something of type [Int] (a list of integers), but actually found something of type [Int] -> [Int] (a function taking a list of integers and returning a list of integers).

Upvotes: 5

bheklilr
bheklilr

Reputation: 54078

First of all, the function last exists already in Prelude, so you don't need to define it yourself. Secondly, please use spaces instead of tabs. This is about the 5th time I've said this on SO this week. Haskell will work with tabs, but it ends up causing problems because in your editor blocks look lined up, but the parser doesn't always see it that way. It also messes up formatting when you copy/paste into stackoverflow.

The problem I found was actually in the definition for rotate:

rotate item (x:xs) = item : move x xs

Here, you're only providing 2 of 3 arguments to move, so you're getting a type error. I got it to compile with

rotate item (x:xs) = item : move x [] xs

But I don't know if that you're desired behavior.

Upvotes: 1

Related Questions