Haskell:Glade 条目的列表理解

发布于 2024-11-28 08:38:07 字数 818 浏览 2 评论 0原文

我想创建一个 entries :: Map(String -> Entry) 这样我就可以轻松地按名称访问每个条目。为此,我有代码

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

(其中 entryList 是条目名称列表,例如 ["name1","name2",...])。

但是,列表理解出现以下错误:

   Couldn't match expected type `[t]' against inferred type `IO Entry'
    In the expression: xmlGetWidget xml castToEntry name
    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 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
    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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

樱娆 2024-12-05 08:38:07

这是因为列表理解中的 <- 期望右侧是一个列表。您尝试使用它来绑定 IO 操作的结果,但这仅在 do 表示法中有效(至少没有扩展)。

问题在于 xmlGetWidget 返回 IO Entry,但您需要 Entry 的映射。这意味着您必须将这些 IO 操作组合成一个更大的操作。

最后,您会想要这样的东西:

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

这里,我创建了一个辅助函数 getEntry :: String -> IO(字符串,条目) 获取条目并将其与其名称配对。

接下来,我使用 mapMgetEntry 映射到名称列表。请注意 mapmapM 之间的区别。如果我使用map,我会得到一个操作列表,即[IO (String, Entry)],当我想要的是返回列表的操作时,即IO [(String, Entry)]

现在,构建了 IO 操作后,我使用 fromList 和运算符 <$> 将其转换为 Map代码>.也称为 fmap<$> 将纯函数应用于 IO 内部的事物,因此结果的类型为 IO(映射字符串条目)

最后,此IO操作的结果可以绑定到entries

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 <
gt; 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文