user121392
user121392

Reputation: 163

Haskell : Possible cause: ‘(:)’ is applied to too many arguments

I‘ve created a nested function which fails at the third nesting. I fail to understand why this pattern holds up for the previous two nests but not the third. I'm attempting to recursively work through the list to add the items in the list together

module Nests 
(nest1,nest2,nest3) where

nest1 :: (Num a) => [a] -> [a] -> [a]
nest1 _ [] = []
nest1 [] _ = []
nest1 (xs:ls1) (xt:ls2) = (xs+xt):nest1 ls1 ls2

nest2 :: (Num a) => [[a]] -> [[a]] -> [[a]]
nest2 _ [] = []
nest2 [] _ = []
nest2 (xs:ls1) (xt:ls2) = (nest1 xs xt):nest2 ls1 ls2

nest3 :: (Num a) => [[[a]]] -> [[[a]]] -> [[[a]]]
nest3 (xs:xt:ls)
    | length ls <= 0 = []
    | otherwise = (nest2 xs xt):nest3 ls

where compiled:

nests.hs:17:19: error:
    • Couldn't match expected type ‘[[[a]]] -> [[[a]]]’
                  with actual type ‘[[[a]]]’
    • Possible cause: ‘(:)’ is applied to too many arguments
      In the expression: (nest2 xs xt) : nest3 ls
      In an equation for ‘nest3’:
          nest3 (xs : xt : ls)
            | length ls <= 0 = []
            | otherwise = (nest2 xs xt) : nest3 ls
    • Relevant bindings include
        ls :: [[[a]]] (bound at nests.hs:15:14)
        xt :: [[a]] (bound at nests.hs:15:11)
        xs :: [[a]] (bound at nests.hs:15:8)
        nest3 :: [[[a]]] -> [[[a]]] -> [[[a]]] (bound at nests.hs:15:1)
   |
17 |     | otherwise = (nest2 xs xt):nest3 ls
   |                   ^^^^^^^^^^^^^^^^^^^^^^

nests.hs:17:33: error:
    • Couldn't match expected type ‘[[[a]]]’
                  with actual type ‘[[[a]]] -> [[[a]]]’
    • Probable cause: ‘nest3’ is applied to too few arguments
      In the second argument of ‘(:)’, namely ‘nest3 ls’
      In the expression: (nest2 xs xt) : nest3 ls
      In an equation for ‘nest3’:
          nest3 (xs : xt : ls)
            | length ls <= 0 = []
            | otherwise = (nest2 xs xt) : nest3 ls
    • Relevant bindings include
        ls :: [[[a]]] (bound at nests.hs:15:14)
        xt :: [[a]] (bound at nests.hs:15:11)
        xs :: [[a]] (bound at nests.hs:15:8)
        nest3 :: [[[a]]] -> [[[a]]] -> [[[a]]] (bound at nests.hs:15:1)
   |
17 |     | otherwise = (nest2 xs xt):nest3 ls

Upvotes: 1

Views: 391

Answers (2)

max taldykin
max taldykin

Reputation: 12908

Type annotation for nest3 does not match its body.

nest3 :: [[[a]]] -> [[[a]]] -> [[[a]]] means that function takes two arguments before returning list but in the function's body you take just one argument.

You can need to fix type signature (or just drop it, GHC is able to infer it):

nest3 :: (Num a) => [[[a]]] -> [[[a]]]
nest3 (xs:xt:ls)
    | length ls <= 0 = []
    | otherwise = (nest2 xs xt):nest3 ls

The problem here is that the first error seems not very relevant. The second one clearly states that nest3 expects one more argument.

• Couldn't match expected type ‘[[[a]]]’
              with actual type ‘[[[a]]] -> [[[a]]]’
• Probable cause: ‘nest3’ is applied to too few arguments

But the first one suggest that (:) is used incorrectly.

• Couldn't match expected type ‘[[[a]]] -> [[[a]]]’
              with actual type ‘[[[a]]]’
• Possible cause: ‘(:)’ is applied to too many arguments

To understand why there are two errors and why the first one is so obscure, consider how GHC works. It tries both to infer types and match inferred types with type annotations provided by the programmer.

Knowing that (:) :: b -> [b] -> [b] we can infer that nest3 ls must be of type [b] in the expression (..) : nest3 ls. Matching this with the provided type [[[a]]] -> [[[a]]] -> [[[a]]] gives the error ‘nest3’ is applied to too few arguments.

Trying to infer type of the otherwise branch in nest3 GHC considers again the type of (:). Applied to two arguments (:) gives a list. Matching this with the provided nest3 type gives ‘(:)’ is applied to too many arguments because only by removing one of the arguments we can get an arrow type.

Upvotes: 2

Hjulle
Hjulle

Reputation: 2615

Regarding the question of why it says ‘(:)’ is applied to too many arguments:

Since your type signature tells Haskell that the function takes two arguments, but you only match for one, it will interpret it as a function returning a function, kind of like in point free style

For example like this

plus :: Int -> Int -> Int
plus x = (+) x

which is equivalent to these

plus' :: Int -> Int -> Int
plus' x y = (+) x y
plus'' :: Int -> Int -> Int
plus'' = (+)


So, in this case, your function is equivalent to

nest3 :: (Num a) => [[[a]]] -> [[[a]]] -> [[[a]]]
nest3 (xs:xt:ls) z
    | length ls <= 0 = [] z
    | otherwise = ((nest2 xs xt):nest3 ls) z
-- or
--  | otherwise = (:) (nest2 xs xt) (nest3 ls) z

Which explains why it thinks (:) might be applied to too many arguments.

Upvotes: 2

Related Questions