我想在换行符上拆分一个字符串,我很惊讶我找不到反函数intercalate "\n"
.也就是说,一个函数将字符串拆分成新行(或根据其他谓词).
请注意lines
并words
做一些不同的事情.例如
intercalate "\n" (lines "a\n") == "a"
还有一个类似的功能函数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中的函数可以更容易地构建它.
如果更原始函数的组合是你在找什么,那么我能想到的基础上比什么没有别的办法unfoldr
和break
,但unfoldr
不是Prelude
.
无论如何,我认为你很清楚,这Prelude
远远不是我们许多人想要的那样,所以毫无疑问它甚至无法解决这样一个看似微不足道的问题.一般的问题Prelude
似乎是它的错误:该模块的目的是提供足以与Haskell一起玩的东西作为介绍的一部分,正如它的名字所示,但由于没有标准的"基础"模块,Haskellers倾向于把它视为一体.
正如尼基塔·沃尔科夫所指出的那样,限制"只有Prelude功能"并不容易,但这里有一个选择:
splitWhen p [] = [[]] splitWhen p l = uncurry (:) . fmap (splitWhen p . drop 1) . break p $ l
这使用Functor
实例(,) a
作为替代Control.Arrow.second
(以避免凌乱的lambda表达式),它可以在不导入任何东西的情况下工作(ghci说"在'GHC.Base'中定义'"),但我不确定它是否真的属于Prelude
,因为我在Haskell报告中找不到它.
编辑:被允许使用其他功能base
甚至没有帮助我那么多.在任何情况下,我会使用second
而不是fmap
因为我认为它增加了一点清晰度.使用unfoldr
,使用Maybe
种子来区分字符串的结尾和空白部分(或示例中的空行):
import Control.Applicative ((<$>)) import Control.Arrow (second) import Data.List (unfoldr) splitWhen p = unfoldr (second check . break p <$>) . Just where check [] = Nothing check (_:rest) = Just rest -- or cramming it into a single line with 'Data.Maybe.listToMaybe' splitWhen' p = unfoldr (second (\rest -> tail rest <$ listToMaybe rest) . break p <$>) . Just