Haskell:Glade 条目的列表理解
我想创建一个 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这是因为列表理解中的
<-
期望右侧是一个列表。您尝试使用它来绑定IO
操作的结果,但这仅在do
表示法中有效(至少没有扩展)。问题在于
xmlGetWidget
返回IO Entry
,但您需要Entry
的映射。这意味着您必须将这些 IO 操作组合成一个更大的操作。最后,您会想要这样的东西:
这里,我创建了一个辅助函数
getEntry :: String -> IO(字符串,条目)
获取条目并将其与其名称配对。接下来,我使用
mapM
将getEntry
映射到名称列表。请注意map
和mapM
之间的区别。如果我使用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 anIO
action, but that's only valid indo
notation (without extensions, at least).The problem is that
xmlGetWidget
returnsIO Entry
, but you want a map ofEntry
. That means you'll have to compose thoseIO
actions into a larger one.In the end, you'll want something like this:
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 mapgetEntry
over the list of names. Note the difference betweenmap
andmapM
. If I had usedmap
, 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 aMap
usingfromList
with the operator<$>
. Also known asfmap
,<$>
applies a pure function to the thing inside theIO
, so the result is of typeIO (Map String Entry)
.Finally, the result of this
IO
action can be bound toentries
.