I tried to implement this challenge from Hackerrank (No Idea! | HackerRank) in Haskell where you add 1 to your count if the number is in set A and subtract -1 if the number is in set B.
import qualified Data.Set as Set
setA :: Set.Set Int
setA = Set.fromList [3,1]
setB :: Set.Set Int
setB = Set.fromList [5,7]
numbers :: List
numbers = [1,5,3]
happinessF :: [Int] -> Set.Set Int -> Set.Set Int -> Int
happinessF set1 set2 = foldr ((+) . cond) 0
where cond x
| Set.member x set1 = 1
| Set.member x set2 = -1
| otherwise = 0
When I run this code, I get an error saying:
Couldnât match expected type: Set.Set Int with actual type: [Int]
The error message says, âCouldnât match expected type: Set.Set Int with actual type: [Int]â. That means exactly what it says: The compiler expects a Set of Ints, but it actually got a list of Ints.
If you think about why that happened, maybe you can see what else might be wrong about your code.
Hint: one way you can fix the problem is by changing the type signature for happinessF.
Also, do look at the full error message which includes detailed location information:
T2.hs:15:28: error:
⢠Couldn't match expected type: Set.Set Int
with actual type: [Int]
⢠In the second argument of âSet.memberâ, namely âset1â
In the expression: Set.member x set1
In a stmt of a pattern guard for
an equation for âcondâ:
Set.member x set1
|
15 | | Set.member x set1 = 1
| ^^^^
That should help you locate the problem.
By the way, one hint for interpreting this error message is that âexpected typeâ means the type the compiler expected at the location it points to, in this case:
Spoiler 1
set1 as argument to the Set.member function.
And âactual typeâ is a constraint from another place in the program, in this case:
Spoiler 2
The type signature of happinessF:
happinessF :: [Int] -> Set.Set Int -> Set.Set Int -> Int
happinessF set1 set2
Note that you donât have to write (x:xs) for every list. You can (and should) just write:
happinessF xs set1 set2 = foldr ((+) . cond) 0 xs
Also because with (x:xs) it will throw an error if you call it with the empty list as argument, because it requires the input list to have at least one element.
The reason behind this is that you can leave arguments out, but only the last argument on both sides of the equality (the = sign). For example if you have:
f x y = g x y
Then you can write:
f x = g x
Or even:
f = g
But if the order of the arguments is different, as in:
f x y = g y x
Then you canât leave out that x argument, because it is not the last argument on the left side of the equality.
So in your case you can only leave of the xs argument if you reorder your arguments:
happinessF :: Set.Set Int -> Set.Set Int -> [Int] -> Int
happinessF set1 set2 xs = foldr ((+) . cond) 0 xs
where ...
Then you can leave out the argument:
happinessF :: Set.Set Int -> Set.Set Int -> [Int] -> Int
happinessF set1 set2 = foldr ((+) . cond) 0
where ...