Reputation: 163
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
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
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