Search code examples
stringhaskellfold

Joining Strings from List into a Single String by Putting Separator in Between Them Using a Fold Function (No Recursion)


We are supposed to create a function in Haskell that takes a string (the separator) and a list of strings, and joining them into a single string by putting the separator in between them. We are not allowed to use recursion and we must use a fold function.

Here are examples:

*Main> join ", " ["one","two","three"]
"one, two, three"
*Main> join "+" ["1","2","3"]
"1+2+3"
*Main> join "X" ["abc"]
"abc"
*Main> join "X" []
""

Now, here is my code:

join :: String -> [String] -> String
join _ [] = ""
join a xs = foldr1 (concat) xs
  where
    concat b c = b ++ a ++ c

My code works for the first two test cases, but produces an error when I have to deal with the "X" separator.

Here is the error message:

*Main> "X" []

<interactive>:190:1: error:
    • Couldn't match expected type ‘[a0] -> t’
                  with actual type ‘[Char]’
    • The function ‘"X"’ is applied to one argument,
      but its type ‘[Char]’ has none
      In the expression: "X" []
      In an equation for ‘it’: it = "X" []
    • Relevant bindings include it :: t (bound at <interactive>:190:1)

*Main> "X" ["abc"]

<interactive>:191:1: error:
    • Couldn't match expected type ‘[[Char]] -> t’
                  with actual type ‘[Char]’
    • The function ‘"X"’ is applied to one argument,
      but its type ‘[Char]’ has none
      In the expression: "X" ["abc"]
      In an equation for ‘it’: it = "X" ["abc"]
    • Relevant bindings include it :: t (bound at <interactive>:191:1)

I'm not really sure what is causing these errors. Any help would be greatly appreciated. Thanks.


Solution

  • In short: you do not call the function. In the example cases, the join function is called:

    *Main> join ", " ["one","two","three"]
    "one, two, three"
    *Main> join "+" ["1","2","3"]
    "1+2+3"
    *Main> join "X" ["abc"]
    "abc"
    *Main> join "X" []
    ""

    If you write "X" ["abc"] in the shell, Haskell will aim to perform function application with "X" the function, but since a String is not a function, the types do not match.

    If you call the function, you get:

    Prelude> :{
    Prelude| join :: String -> [String] -> String
    Prelude| join _ [] = ""
    Prelude| join a xs = foldr1 (concat) xs
    Prelude|   where
    Prelude|     concat b c = b ++ a ++ c
    Prelude| :}
    Prelude> join ", " ["one", "two", "three"]
    "one, two, three"
    Prelude> join "+" ["1", "2", "3"]
    "1+2+3"
    Prelude> join "X" ["abc"]
    "abc"
    Prelude> join "X" []
    ""