【问题标题】:Haskell: List comprehension of Glade entriesHaskell:对 Glade 条目的列表理解
【发布时间】:2011-08-06 07:27:29
【问题描述】:

我想创建一个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]'

我不明白为什么它需要一个列表。有人可以帮忙吗?

【问题讨论】:

    标签: list haskell list-comprehension glade


    【解决方案1】:

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

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

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

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

    在这里,我创建了一个辅助函数 getEntry :: String -&gt; IO (String, Entry) 来获取条目并将其与其名称配对。

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

    现在,在构造了 IO 动作之后,我使用 fromList 和运算符 &lt;$&gt; 将其转换为 Map。也称为fmap&lt;$&gt; 将纯函数应用于IO 内的事物,因此结果为IO (Map String Entry) 类型。

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

    【讨论】:

    • 由于某种原因,我的 ghc 无法识别 &lt;$&gt;,但我能够识别 entries ← fromList `fmap` mapM getEntryTuple entryList。感谢您的描述!
    • &lt;$&gt;Control.Applicative 中。
    猜你喜欢
    • 2022-01-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多