Is there a function to concatenate elements of a list with a separator? For example:
> foobar " " ["is","there","such","a","function","?"]
["is there such a function ?"]
Thanks for any reply!
Yes, there is:
Prelude> import Data.List
Prelude Data.List> intercalate " " ["is","there","such","a","function","?"]
"is there such a function ?"
intersperse is a bit more general:
Prelude> import Data.List
Prelude Data.List> concat (intersperse " " ["is","there","such","a","function","?"])
"is there such a function ?"
Also, for the specific case where you want to join with a space character, there is unwords:
Prelude> unwords ["is","there","such","a","function","?"]
"is there such a function ?"
unlines works similarly, only that the strings are imploded using the newline character and that a newline character is also added to the end. (This makes it useful for serializing text files, which must per POSIX standard end with a trailing newline)
intercalate "," ["some", "", "string"] = "some,,string" and intercalate "" ["foo", "bar"] = "foobar"unlines adds a newline to each line, that is unlines ["A", "B"] = "A\nB\n", so it is not the same as intercalate.unwords.It's not hard to write one-liner using foldr
join sep xs = foldr (\a b-> a ++ if b=="" then b else sep ++ b) "" xs
join " " ["is","there","such","a","function","?"]
join which accepts a separator and a string list. It then applies fold on the list using an anonymous lambda function. In (\a b-> a ++ if b=="" then b else sep ++ b) a is the accumulator, b is the next item on the list. The fold starts with ""Some other ideas of implementations of intersperse and intercalate, if someone is interested:
myIntersperse :: a -> [a] -> [a]
myIntersperse _ [] = []
myIntersperse e xs = init $ xs >>= (:[e])
myIntercalate :: [a] -> [[a]] -> [a]
myIntercalate e xs = concat $ myIntersperse e xs
xs >>= f is equivalent to concat (map f xs).
If you wanted to write your own versions of intercalate and intersperse:
intercalate :: [a] -> [[a]] -> [a]
intercalate s [] = []
intercalate s [x] = x
intercalate s (x:xs) = x ++ s ++ (intercalate s xs)
intersperse :: a -> [a] -> [a]
intersperse s [] = []
intersperse s [x] = [x]
intersperse s (x:xs) = x : s : (intersperse s xs)
intersperse needn't be Strings, but intercalate would need to at least be Show, and if you did use Show, you'd need some way to deal with them using Strings anyway. I'm still getting used to how Haskell deals with mixed infix and prefix functions/operators, and I prefer bracketing when mixing in case I end up wanting to use $intercalate :: [a] -> [[a]] -> [a] - why Show? As for syntax, Haskell doesn't have any prefix operators (except for -, which is an abomination), and function application binds tighter than any infix operator: x:s:intersperse s xs is fine (but it reads much better if you put the spaces in: x : s : intersperse s xs (I don't really understand why people like to leave out the spaces around :)).Show was because I was assuming you'd want the result to be a String. By "infix and prefix functions/operators" I meant "prefix functions and infix operators", but that was unclear. Unary - is death. As for the :s and other infix operators, whether I use spaces depends highly on context, but I'm always locally consistent. eg, (:) in a pattern match never has spaces, but elsewhere it depends on whether it's bracketed and on my mood.
unwords[String] -> String -> Stringin case that the other way returns no answer, right?[a] -> (a -> b) -> [b]returnsmapas its first result.