【问题标题】:Haskell Recursive function over IO listIO列表上的Haskell递归函数
【发布时间】:2011-10-19 04:17:55
【问题描述】:

我有以下函数迭代列表[(Map String SqlValue)]

extractPatternStrings ∷ IO [(Map String SqlValue)] → IO [String] 
extractPatternStrings [] = do
    return []
extractPatternStrings lst = do
    (m:ms) ←  lst
    return $ (toString m) : (extractPatternStrings ms)
    where
        toString ∷  Map String SqlValue → String 
        toString m = (fromSql . fromJust . (Map.lookup "word"))∷ String

执行空列表案例告诉我它无法将预期的IO [Map String SqlValue] 与实际的[t0] 匹配。

我认为do = return 会解决这个问题。我应该如何纠正这个问题?

编辑:回答我为什么使用 IO:

selectAll ↠ extractPatternStrings 调用该函数,其中 selectAll 从数据库中读取。

【问题讨论】:

  • 为什么在这里使用IO?这看起来可能是一个纯函数。
  • 我正在使用 IO,因为我从数据库中读取。如果我不使用 IO,数据库读取代码会给我一个错误,想要“返回”一个 IO。

标签: haskell recursion io


【解决方案1】:
extractPatternStrings ∷ IO [(Map String SqlValue)] → IO [String]

IO [String] 是一个产生[String] 结果的 IO 操作。您使用 do 表示法可确保 extractPatternStrings 生成 IO [String],而不是 [String]

IO [(Map String SqlValue)] 是一个产生[Map String SqlValue] 结果的 IO 操作。但是您不能对 IO 操作进行模式匹配。您使用的语法是直接针对列表进行匹配,而不是针对生成列表的 IO 操作。

您应该改用这种类型签名:

extractPatternStrings ∷ [Map String SqlValue] → IO [String] 

除了@missingno 指出的那样,这不需要是 IO 操作:

extractPatternStrings ∷ [Map String SqlValue] → [String] 
extractPatternStrings []     = []
extractPatternStrings (m:ms) = toString m : extractPatternStrings ms
    where
        toString ∷  Map String SqlValue → String 
        toString m = (fromSql . fromJust . (Map.lookup "word"))∷ String

或者,更好(并修复toString 中的错误):

extractPatternStrings ∷ [Map String SqlValue] → [String] 
extractPatternStrings = map toString
    where
        toString ∷  Map String SqlValue → String 
        toString = fromSql . fromJust . Map.lookup "word"

更简洁:

extractPatternStrings ∷ [Map String SqlValue] → [String] 
extractPatternStrings = map (fromSql . fromJust . Map.lookup "word")

如果你真的必须有原始签名,那么使用liftM,或者将你的调用代码更改为selectAll ↠ liftM extractPatternStrings(我必须承认我不认识你在那里使用的运算符),或者定义@987654336 @as

extractPatternStrings ∷ IO [Map String SqlValue] → IO [String] 
extractPatternStrings = liftM $ map (fromSql . fromJust . Map.lookup "word")

但我推荐前者。

【讨论】:

  • 我设法让它与前者一起工作。谢谢你的帮助!哦,那个操作员是>>=。我的编辑器只是将其转换为 unicode 符号。
【解决方案2】:

return 将您的返回值包装在 IO 中,以便处理返回类型 IO [String]。但是,它对您的参数类型([(Map String SqlValue)])没有帮助,但您尝试对空列表进行模式匹配。基本上你不能对 IO 值进行模式匹配。

因此,您应该摆脱 IO(在您的代码中似乎完全没有必要),或者如果您确实希望该函数接受 IO(尽管我无法想象您为什么会这样做),您必须打开包装你的论点在你可以对它进行模式匹配之前,看起来像这样:

extractPatternStrings lstIO = do
  lst <- lstIO
  case lst of
    [] -> ...
    (m:ms) -> ...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-06
    • 2011-09-01
    • 2011-08-21
    • 1970-01-01
    • 2017-06-22
    • 2019-03-26
    相关资源
    最近更新 更多