Reputation: 449
Here is an example of my code that is producing the error:
amount :: [Int, Int, Int] -> Int
amount [(a, b, c)] = sum( map getBalance [(a, b, c)])
where getBalance :: (Int,Int,Int) -> Int
getBalance (d, e, f) = f
amount [] = 0
Originally the code was just:
amount :: [Int, Int, Int] -> Int
amount [(a, b, c)] = sum [c]
But I tried rewriting and adding things to see if I could find the cause of the error, and I couldn't. I'm rather new to Haskell, so if it's a stupid error I apoligise.
Upvotes: 1
Views: 828
Reputation: 54584
I certainly wouldn't recommend to make Int
a Monoid
in "serious" code, but it would work:
import qualified Data.Foldable as F
import Data.Monoid
amount :: [(Int,Int,Int)] -> Int
amount xs = let (_,_,x) = F.fold xs in x
instance Monoid Int where
mempty = 0
mappend = (+)
Upvotes: 0
Reputation: 15877
The type signature you've written describes a list of three Ints: [Int, Int, Int]
. The list types have indeterminate length, however, and the amount function you've written seems to expect 3-tuples of Ints, which would be written as [(Int, Int, Int)]
; this can be derived from the definition anyway. Loading the first code block into ghci therefore produced:
test.hs:1:11:
Illegal type: '[Int, Int, Int]
The second error appears once I provide it with a longer list of input:
*Main> amount [(1,2,3),(4,5,6)]
*** Exception: test.hs:(2,1)-(5,13): Non-exhaustive patterns in function amount
The problem here is that neither of the patterns match: you have patterns for lists with one or zero entries, but not more. Seeing that [(a, b, c)]
is a repeated expression, how about we just replace it?
amount [] = 0
amount xs = sum( map getBalance xs)
where getBalance :: (Int,Int,Int) -> Int
getBalance (d, e, f) = f
Now any length of list will be passed to map
, which is fine, because it is meant to handle an arbitrary length. So is sum
, actually, so we didn't even need to add the special case for an empty list.
If you want to add a pattern for the longer-than-one lists, the traditional form is x:xs
, breaking it up into a head x
and tail xs
. That pattern doesn't match the empty list, because it cannot be split.
The problem with your original code was also that it only defined a version for a list of one tuple. We can use list comprehension or map to handle that:
amount1 abcs = sum [c | (a,b,c) <- abcs]
amount2 = sum . map (\(a,b,c) -> c)
All of these variants do the same thing, even though amount2 didn't even mention an argument.
Upvotes: 4
Reputation: 796
First, your type signature is wrong, it has to be
amount :: [(Int, Int, Int)] -> Int
The "Non-Exhaustive pattern Error occurs, because you provided only two cases of lists:
At the bottom the case for empty list [], and above the case, where the list holds one element
([(a,b,c)]
is a list with the element (a,b,c)
. Hence your code would work with amount [(1,2,3)]
)
Easiest way: Replace [(a,b,c)]
with xs
, at the left of the = and the right.
Upvotes: 1
Reputation: 1622
(a,b,c)
is a tuple: (a,b,c) = (,,) a b c
amount :: [(Int, Int, Int)] -> Int
amount [(a, b, c)] = ...
The right one
Upvotes: 0