Haskell使用foldl之类的递归

时间:2014-01-22 22:34:03

标签: haskell recursion types fold

我正在尝试使用foldl的函数 浏览元组列表并从中创建一个字符串。 我正在尝试创建一个已经使用递归工作的类似函数。

以下是我正在尝试编译的代码:

citeBook :: (String, String, Integer) -> String
citeBook (name, titl, date) = (titl ++ " (" ++ name ++ ", " ++ show date ++ ")\n")

--Recursion function
-- function must be called with putStr in order for newlines to work
bibliography_rec :: [(String, String, Integer)] -> String
bibliography_rec [] = ""
bibliography_rec xs = (citeBook(head xs) ++ bibliography_rec (tail xs))

--foldl function 
bibliography_fold :: [(String, String, Integer)] -> String
bibliography_fold [] = ""
bibliography_fold (x:xs) = foldl (++) citeBook(x) xs   --ERROR HERE

所以在提供的代码的最后一行,我正在尝试使用foldl 使用(++)作为运算符,以便组合列表中的字符串。 我使用citeBook(x)作为我的基本情况,因为x将是第一个元组 取自列表。请注意,citeBook(x)返回一个字符串。然后继续 用列表xs折叠。

以下是我遇到的错误。我认为我的foldl参数类型不是 符合预期,但一切似乎都没关系..

hw1.hs:28:34:
    Couldn't match type `[a0]'
                  with `(String, String, Integer) -> String'
    Expected type: ((String, String, Integer) -> String)
                   -> [a0] -> (String, String, Integer) -> String
      Actual type: [a0] -> [a0] -> [a0]
    In the first argument of `foldl', namely `(++)'
    In the expression: foldl (++) citeBook (x) xs
    In an equation for `bibliography_fold':
        bibliography_fold (x : xs) = foldl (++) citeBook (x) xs

hw1.hs:28:48:
    Couldn't match expected type `[[a0]]'
                with actual type `(String, String, Integer)'
    In the third argument of `foldl', namely `(x)'
    In the expression: foldl (++) citeBook (x) xs
    In an equation for `bibliography_fold':
        bibliography_fold (x : xs) = foldl (++) citeBook (x) xs

hw1.hs:28:51:
    Couldn't match expected type `(String, String, Integer)'
                with actual type `[(String, String, Integer)]'
    In the fourth argument of `foldl', namely `xs'
    In the expression: foldl (++) citeBook (x) xs
    In an equation for `bibliography_fold':
        bibliography_fold (x : xs) = foldl (++) citeBook (x) xs

我感谢任何反馈。谢谢!

2 个答案:

答案 0 :(得分:4)

您向foldl (++)函数提供了类型为String -> String -> String的函数。但是,您折叠的收藏集xs的类型为[(String, String, Integer)],而不是[String]类型。

您可以将bibliography_fold更改为

bibliography_fold :: [(String, String, Integer)] -> String
bibliography_fold [] = ""
bibliography_fold (x:xs) = foldl (++) (citeBook x) (map citeBook xs)

或只是

bibliography_fold :: [(String, String, Integer)] -> String
bibliography_fold xs = foldl (++) "" (map citeBook xs)

但我自己是Haskell的亲戚,所以请把我的编码风格带上一粒盐。

此外,您需要编写(citeBook x)而不是citeBook(x),否则编译器会认为citeBook(x)都是foldl的参数(正确)我,如果我错了)。这有助于解释为什么你得到的错误信息看起来很奇怪。

答案 1 :(得分:3)

您已经得到了答案,因此我将提供另一种使用折叠来解决此问题的方法:

bibliography_fold :: [(String, String, Integer)] -> String
bibliography_fold = foldr ((++) . citeBook) ""

没有地图,没有特殊情况,它可以用自由点风格书写。我鼓励你在GHCi中解构这个表达式,并使用:info检查每个组件以探索它是如何工作的。查看foldr++citeBook(++) . citeBook的类型,看看您是否可以找出其工作原理。您可能还想查找foldr的源代码。