Reputation: 502
I have a problem with implementing a maybe type in to list manipulation!
What I need to do is:
ljoin [(2,"S"),(1,"J")] [(2,1),(2,2),(3,4)]
outputs: [(2,"S",Just 1),(2,"S",Just 2),(1,"J",Nothing)]
What I written so far:
ljoin :: Eq a => [(a,b)] -> [(a,c)] -> [(a,b,Maybe c)]
ljoin xs ys = [if xs==ys then (xa, xb, Just yc) else (xa, xb, Nothing) | (xa, xb) <- xs, (ya, yc) <- ys]
Which produces the error:
Inferred type is not general enough
*** Expression : ljoin
*** Expected type : Eq a => [(a,b)] -> [(a,c)] -> [(a,b,Maybe c)]
*** Inferred type : Eq a => [(a,b)] -> [(a,b)] -> [(a,b,Maybe b)]
Am I on the right track doing it this way and just need to keep at it until I find what I am doing wrong, or is there a better way?
Upvotes: 1
Views: 354
Reputation: 15121
According to your example, I believe what you want ljoin
to to is this:
for each element (xa, xb) of xs
if there are elements in ys that xa == ya, then
for each of these element (ya, yb) generates a (xa, xb, Just yb)
else
generates a (xa, xb, Nothing)
This could be translated to Haskell code directly:
ljoin xs ys = concatMap join xs
where join (xa, xb) = case filter (\(ya, yb) -> xa == ya) ys of
[] -> [(xa, xb, Nothing)]
ys' -> map (\(_, yb) -> (xa, xb, Just yb)) ys'
Upvotes: 2
Reputation: 60463
The subexpression xs == ys
forces xs
and ys
to have the same type.
(==) :: (Eq a) => a -> a -> Bool
Calling this on your two lists forces [(a,b)] = [(a,c)]
, hence b = c
. But you've declared in the type that you have two independent type variables, so unifying these is not allowed.
It looks to me like you should be comparing the actual first elements you got, rather than the lists as a whole.
Upvotes: 7