Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Haskell using foldl like recursion

I'm trying to get a function working that uses foldl to go through a list of tuples and create a string from it. I'm trying to create a similar function that already works using recursion.

Here is the code that I'm trying to compile:

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

So in the very last line of the provided code, I am trying to have foldl use (++) as the operator in order to combine the strings in the list. I'm using citeBook(x) as my base case, since x will be the first tuple taken from the list. Note that citeBook(x) returns a string. Then continue folding with the list xs.

Here are the errors I'm getting. I think my parameter types for foldl aren't matching up with what is expected, but everything seems okay to me..

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

I appreciate any and all feedback. Thanks!

like image 969
Kyle N Avatar asked Mar 21 '23 20:03

Kyle N


1 Answers

You gave foldl the (++) function which has type String -> String -> String. However the collection you're folding over, xs, has type [(String, String, Integer)], not type [String].

You could change bibliography_fold to

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

or just to

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

but I'm a relative noob at Haskell myself so take my coding style with a grain of salt.

Also, you need to write (citeBook x) and not citeBook(x), or the compiler will assume that citeBook and (x) are both arguments to foldl (correct me if I'm wrong). This helps explain why the error message you got is so strange-looking.

like image 155
jcarpenter2 Avatar answered Mar 29 '23 02:03

jcarpenter2