String 如何实现“反”的功能;插入;(将字符串拆分为字符上的片段)使用来自;“基”是什么;?
我想在换行符上拆分一个字符串,我很惊讶我找不到要拆分的反函数。也就是说,一个将字符串拆分为新行(或根据其他谓词)上的片段的函数 请注意,String 如何实现“反”的功能;插入;(将字符串拆分为字符上的片段)使用来自;“基”是什么;?,string,list,haskell,split,String,List,Haskell,Split,我想在换行符上拆分一个字符串,我很惊讶我找不到要拆分的反函数。也就是说,一个将字符串拆分为新行(或根据其他谓词)上的片段的函数 请注意,行和字做了一些不同的事情。比如说 intercalate "\n" (lines "a\n") == "a" 拆分库中有一个类似的函数。我也可以自己直接编写这样一个函数: splitOn :: (a -> Bool) -> [a] -> [[a]] splitOn p = map reverse . g [] where g rs
行
和字
做了一些不同的事情。比如说
intercalate "\n" (lines "a\n") == "a"
拆分库中有一个类似的函数。我也可以自己直接编写这样一个函数:
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
但是我想知道,如果只使用来自的函数,是否可以更容易地构造它。如果您正在寻找更原始的函数的组合,那么除了基于
unfover
和break
的方法,我想不出其他方法,但是unfover
不在前奏曲中
无论如何,我想你很清楚,Prelude
远远不是我们很多人想要的,所以它甚至不能解决这样一个看似微不足道的问题也就不足为奇了。《序曲》
的一般问题似乎是它的曲解不当:该模块旨在提供足以与Haskell一起玩的东西作为介绍的一部分,正如其名称所示,但由于没有标准的“基本”模块,Haskeller倾向于将其视为一个。正如Nikita Volkov指出的,限制“仅前奏曲功能”并不容易,但这里有一个选项:
splitWhen p [] = [[]]
splitWhen p l = uncurry (:) . fmap (splitWhen p . drop 1) . break p $ l
这使用了(,)a
的函子
实例作为控件.Arrow.second
(以避免使用messier lambda表达式)的替代方法,该方法无需导入任何内容(ghci表示“在'GHC.Base'中定义”),但我不确定这是否真的属于序言
,因为我在Haskell报告中找不到它
编辑:允许使用base
中的其他函数对我没有多大帮助。无论如何,我会使用second
而不是fmap
,因为我认为这会增加一点清晰度。使用展开器
,使用可能
作为种子来区分字符串的结尾和空白y部分(或示例中的空行):
import-Control.Applicative(())
导入控制。箭头(第二个)
导入数据列表(展开器)
当p=展开器时拆分(第二次检查。断开p)。只需
哪里
检查[]=无
检查(u:rest)=只需休息
--或者用“Data.Maybe.listToMaybe”把它塞进一行
拆分时间'p=
展开器(第二个(\rest->tail rest)这与Data.List.Split中的splitOn
不同。这一个具有类型签名[a]->[a]->[[a]]
,而您的类型签名相当于a->[a]->[[a]]
。区别在于在子字符串上拆分或在单个字符上拆分。但是我们有来自parsercompbinators
的sebby
,这个splitOn
类似于Data.List.Split.splitWhen
。你必须使用字符串类型吗?文本和ByteString.Char8
都有spl它
用于分解字符串的函数。@LukeTaylor很遗憾,是的。我想参与的库没有使用任何函数,我觉得只为这个函数添加依赖项不是很好。对不起,我把问题说错了。我的意图是只使用“base”中的函数,而不需要额外的库包,而不仅仅是Prelude模块。对不起,我把问题说错了。我的意图是只使用“base”中的函数,而不需要额外的库包,而不仅仅是Prelude模块。
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