如何实现"插入"的反转(使用" base"中的函数将字符串拆分成字符)

时间:2013-12-23 19:58:01

标签: string list haskell split

我想在换行符上拆分一个字符串,我很惊讶我找不到intercalate "\n"的反函数。也就是说,一个函数将字符串拆分成新行(或根据其他谓词)。

请注意lineswords做了不同的事情。例如

intercalate "\n" (lines "a\n") == "a"

split 库中有一个类似的函数函数splitOn。我也可以直接自己编写这样的函数:

splitOn :: (a -> Bool) -> [a] -> [[a]]
splitOn p = map reverse . g []
  where
    g rs []                 = [rs]
    g rs (x:xs) | p x       = rs : g [] xs
                | otherwise = g (x : rs) xs

但我想知道是否只使用base中的函数可以更轻松地构建它。

2 个答案:

答案 0 :(得分:5)

如果您正在寻找更原始函数的组合,那么除了基于unfoldrbreak的内容之外我别无其他想法,但unfoldr不是在Prelude

无论如何,我认为你很清楚Prelude远非我们许多人想要的那样,所以毫无疑问它甚至无法解决这个看似微不足道的问题。 Prelude的一般问题似乎是错误的:该模块的目的是提供足以与Haskell一起玩的东西作为介绍的一部分,正如其名称所暗示的那样,但由于没有标准的“基础”模块,Haskellers倾向于将其视为一个。

答案 1 :(得分:5)

正如尼基塔·沃尔科夫指出的那样,限制“只有Prelude功能”并不容易,但这里有一个选择:

splitWhen p [] = [[]]
splitWhen p l  = uncurry (:) . fmap (splitWhen p . drop 1) . break p $ l

这使用Functor的{​​{1}}实例替代(,) a(以避免凌乱的lambda表达式),它可以在不导入任何内容的情况下工作(ghci说“在GHC中定义”。 Base'“),但我不确定它是否真的属于Control.Arrow.second,因为我在Haskell报告中找不到它。

编辑:允许使用Prelude中的其他功能甚至不能帮助我。在任何情况下,我都会使用base代替second,因为我认为它会增加一些清晰度。使用fmap,使用种子unfoldr来区分字符串的结尾和空白部分(或示例中的空行):

Maybe