开发者

Haskell: List comprehension of Glade entries

I want to make an entries :: Map(String -> Entry) so I can easily access each entry by name. To this end, I have the code

  Just xml ←  xmlNew "blah.glade"
  ...
  entries ← fromList $ [(name,entry) | name <- entryList 
      , entry <- xmlGetWidget xml castToEntry name]

(where entryList is a list of entry names, e.g. ["name1","name2",...]).

However, the list comprehension comes up with the following error:

   Couldn't match expected type `[t]' against inferred type `IO Entry'
    In the expression: xmlGetWidget xml castToEntry name
  开发者_Python百科  In a stmt of a list comprehension:
        entry <- xmlGetWidget xml castToEntry name
    In the second argument of `($)', namely
        `[(name, entry) |
              name <- entryList, entry <- xmlGetWidget xml castToEntry name]'

I can't see why it's expecting a list of anything. Can anyone help with this?


It's because <- in a list comprehension expects the right hand side to be a list. You're trying to use it to bind the result of an IO action, but that's only valid in do notation (without extensions, at least).

The problem is that xmlGetWidget returns IO Entry, but you want a map of Entry. That means you'll have to compose those IO actions into a larger one.

In the end, you'll want something like this:

let getEntry name = do entry <- xmlGetWidget xml castToEntry name
                       return (name, entry)
entries <- fromList <$> mapM getEntry entryList

Here, I've created a helper function getEntry :: String -> IO (String, Entry) to get the entry and pair it up with its name.

Next, I use mapM to map getEntry over the list of names. Note the difference between map and mapM. If I had used map, I would have gotten a list of actions, i.e. [IO (String, Entry)], when what I want is an action returning a list, i.e. IO [(String, Entry)].

Now, having constructed that IO action, I convert it to a Map using fromList with the operator <$>. Also known as fmap, <$> applies a pure function to the thing inside the IO, so the result is of type IO (Map String Entry).

Finally, the result of this IO action can be bound to entries.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜