noko
noko

Reputation: 1129

Using lookup with an IO list?

I am getting the contents of a file and transforming it into a list of form:

[("abc", 123), ("def", 456)]

with readFile, lines, and words.

Right now, I can manage to transform the resulting list into type IO [(String, Int)].

My problem is, when I try to make a function like this:

check x = lookup x theMap

I get this error, which I'm not too sure how to resolve:

Couldn't match expected type `[(a0, b0)]'
            with actual type `IO [(String, Int)]'
In the second argument of `lookup', namely `theMap'

theMap is essentially this:

getLines :: String -> IO [String]
getLines = liftM lines . readFile

tuplify [x,y] = (x, read y :: Int)

theMap = do
    list <- getLines "./test.txt"
    let l = map tuplify (map words list)
    return l

And the file contents are:

abc 123
def 456

Can anyone explain what I'm doing wrong and or show me a better solution? I just started toying around with monads a few hours ago and am running into a few bumps along the way.

Thanks

Upvotes: 2

Views: 169

Answers (1)

Sarah
Sarah

Reputation: 6696

You will have to "unwrap" theMap from IO. Notice how you're already doing this to getLines by:

do
  list <- getlines
  [...]
  return (some computation on list)

So you could have:

check x = do
  m <- theMap
  return . lookup x $ m

This is, in fact, an antipattern (albeit an illustrative one,) and you would be better off using the functor instance, ie. check x = fmap (lookup x) theMap

Upvotes: 4

Related Questions