Zast
Zast

Reputation: 502

How to deal with Maybe type in Haskell list comprehensions II

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

Answers (2)

Lee Duhem
Lee Duhem

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

luqui
luqui

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

Related Questions