Haskell: looking up the second value of a tuple in a list based on the first value
Question
I've got a function here that is meant to look through a list of tuples and find the second value in the tuple by taking in the first value. Here's the function so far:
lookup :: String -> [(String,String)] -> String
lookup _ _ [] = "Not found"
lookup x y zs = if (notFound x zs)
then "Not found"
else (head [b | (a,b) <- zs, (a==x)])
The notFound function just returns a Bool as true if there is no tuple containing the given first string. Problem is, I get this type error in Hugs:
ERROR "find.hs" (line 22): Type error in explicitly typed binding
*** Term : lookup
*** Type : String -> [(String,String)] -> [a] -> String
*** Does not match : String -> [(String,String)] -> String
I'm thinking it's something to do with the dummy "Not found" value having a different type to the string from the generated list, but I'm not sure.
Solution
I think your explicit type-declaration is wrong. You have:
lookup :: String -> [(String,String)] -> String
but I think it should be
lookup :: String -> String -> [(String,String)] -> String
Actually, after taking another look at it, it looks like you're not using the 2nd parameter "y". So you could remove it and the underscore like so
lookup :: String -> [(String,String)] -> String
lookup _ [] = "Not found"
lookup x zs = if (notFound x zs)
then "Not found"
else (head [b | (a,b) <- zs, (a==x)])
This will allow you to keep the type declaration you have.
OTHER TIPS
by the way, did you know that Haskell Prelude already has a "lookup" function to look up entries in an association list? here is the type signature (it is more general, accepting any key type which instances Eq):
lookup :: (Eq a) => a -> [(a,b)] -> Maybe b
so your function would accomplish something like the below
myLookup x zs = Maybe.fromMaybe "Not found" $ lookup x zs
At a glance, it looks like maybe the second parameter should be removed (the 'y' and the second underscore)? lookup is declared to take two parameters, not three.