Alex
Alex

Reputation: 325

Function applied to too many arguments error

When I try to compile the following code:

matcHelp :: String -> Stack Char -> Stack Char
matcHelp b = mtHelp b (MakeS([])) (MakeS([])) where 
                      mtHelp b result1 result2 =
                          if (b == [])
                              then result1 result2
                          else if head b == '('
                              then mtHelp (tail b) (push '(' result1) (result2)
                          else if head b == '['
                              then mtHelp (tail b) (result1) (push '[' result2)
                          else if (head b == ')')
                              then mtHelp (tail b) (popOut result1) (result2)
                          else if (head b == ']')
                              then mtHelp (tail b) (result1) (popOut result2)
                          else mtHelp (tail b) (result1) (result2)

I get that the function push:

push :: a -> Stack a -> Stack a
push x (MakeS(xs)) = MakeS(x:xs)

is applied to too many arguments, specifically in the instance (push '(' result1). I don't see why?

The actual error I'm getting is:

Couldn't match expected type `t1 -> t0' with actual type `Stack a0'
    In the return type of a call of `push'
    Probable cause: `push' is applied to too many arguments
    In the second argument of `mtHelp', namely `(push '(' result1)'
    In the expression: mtHelp (tail b) (push '(' result1) (result2)
Failed, modules loaded: none.

Note: MakeS is a data constructor

newtype Stack a = MakeS([a]) deriving Show

Upvotes: 0

Views: 2811

Answers (1)

cdk
cdk

Reputation: 6778

The issue is the line

if (b == []) then result1 result2

implies result1 is a function to be applied to result2. From your type signature, matchHelp is supposed to be returning a Stack Char, so you've made an error here.

From your comments it's clear that you want to return multiple values from matchHelp. In Haskell, all functions take one argument and return one result, always. Even a function like

(+) :: Int -> Int -> Int

takes one argument (an Int) and returns one result (a function Int -> Int). You could write the type signature like this:

(+) :: Int -> (Int -> Int)

but Haskell does this for you anyways. This is called "currying".

The Haskell way to return multiple values is to return a single tuple containing those values or a data structure that you've defined yourself.

Unrelated, your function is not very "Haskell-y" with all those if .. then .. else and head/tail when pattern matching and guards should be used instead. Here's the rewritten function with multiple return values in a tuple.

matchHelp :: String -> Stack Char -> (Stack Char, Stack Char)
matchHelp b = mtHelp b (MakeS []) (MakeS [])
    where mtHelp []     result1 result2 = (result1, result2)
          mtHelp (x:xs) result1 result2     
            | x == '('  = mtHelp xs (push '(' result1) (result2)
            | x == '['  = mtHelp xs (result1) (push '[' result2)
            | x == ')'  = mtHelp xs (popOut result1) (result2) 
            | x == ']'  = mtHelp xs (result1) (popOut result2)
            | otherwise = mtHelp xs result1 result2 

Upvotes: 5

Related Questions