连接字符串列表,使用foldl-Haskell在字符串之间添加分隔符

连接字符串列表,使用foldl-Haskell在字符串之间添加分隔符,haskell,foldleft,Haskell,Foldleft,我有一个函数,用于在列表中组合字符串,在每个字符串之间添加分隔符,并使用foldl输出单个字符串。下面是我所拥有的和函数的一些预期行为——它不工作,我不确定为什么 -- | `sepConcat sep [s1,...,sn]` returns `s1 ++ sep ++ s2 ++ ... ++ sep ++ sn` -- -- >>> sepConcat "---" [] -- "" -- -- >>> sepConcat ", " ["foo", "ba

我有一个函数,用于在列表中组合字符串,在每个字符串之间添加分隔符,并使用foldl输出单个字符串。下面是我所拥有的和函数的一些预期行为——它不工作,我不确定为什么

-- | `sepConcat sep [s1,...,sn]` returns `s1 ++ sep ++ s2 ++ ... ++ sep ++ sn`
--
-- >>> sepConcat "---" []
-- ""
--
-- >>> sepConcat ", " ["foo", "bar", "baz"]
-- "foo, bar, baz"
--
-- >>> sepConcat "#" ["a","b","c","d","e"]
-- "a#b#c#d#e"

sepConcat :: String -> [String] -> String
sepConcat sep []     = ""
sepConcat sep (x:xs) = foldLeft f base l
  where
    f a x            = a ++ sep ++ x
    base             = ""
    l                = xs

我认为您可以通过检查第一个参数是否为空字符串并相应地处理它来解决这个问题

sepConcat sep = foldl (\x y -> if x == "" then y else x ++ sep ++ y) ""
-- or
sepConcat sep = foldl combine ""
  where combine "" x = x
        combine x y = x ++ sep ++ y


最大的问题是模式匹配:

sepConcat sep []     = ""
sepConcat sep (x:xs) = foldLeft f base l
您不需要在
[]
(x:xs)
中再次划分模式,因为foldlfoldr会处理这两种情况。这就是如何定义
foldl
以递归方式列出:

foldLeft :: (b -> a -> b) -> b -> [a] -> b
foldLeft f base []     = base
foldLeft f base (x:xs) = f (foldLeft f base xs) x
您只需正确应用这两种情况:

sepConcat :: String -> [String] -> String
sepConcat sep xs = foldLeft (\rs s ->
 if null rs 
 then s ++ rs
 else s ++ sep ++ rs) "" xs
这里,空列表的大小写是
,函数用于列表的递归大小写

以你的例子:

sepConcat ", " ["foo", "bar", "baz"]
=> "foo, bar, baz"