Haskell在IO列表上的递归函数

时间:2011-10-18 19:35:47

标签: haskell recursion io

我有以下函数迭代列表[(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从数据库中读取。

2 个答案:

答案 0 :(得分:7)

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

IO [String]是一个产生[String]结果的IO操作。您使用记号确保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(我必须承认我不认识您在那里使用的运算符),或者将extractPatternStrings定义为

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

但我推荐前者。

答案 1 :(得分:2)

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

所以你应该摆脱IO(你的代码中似乎完全没有必要)或者如果你真的希望函数采用IO(虽然我无法想象为什么你会这样做),你必须解开在你可以对它进行模式匹配之前你的论点,看起来像这样:

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