所以有这个
type DocName = FilePath
type Line = (Int,String)
type Document = [Line]
splitLines :: String -> Document
splitLines [] = []
splitLines str = zip [0..(length listStr)] listStr
where
listStr = [getLine] ++ map snd (splitLines getRest)
getLine = (takeWhile (/='\n') str)
getRest = (dropWhile (=='\n') (dropWhile (/='\n') str))
工作正常,但我想我也需要空行。
splitLines "test\nthis\nstring\n" should be
[(0,"test"),(1,"this"),(2,"string"),(3,"")]
我不确定如何做到这一点。有任何想法吗? 我需要用别的东西重写它吗?
我应该使用像foldr这样的高阶函数吗? 感谢。
终于想通了。
splitLines :: String -> Document
splitLines "" = [(0,"")]
splitLines str = zip [0..(length listStr)] listStr
where
listStr = [getLine] ++ map snd (splitLines getRest)
getLine = takeWhile (/='\n') str
getRest = tail (dropWhile (/='\n') str)
答案 0 :(得分:2)
它正在丢弃空行,因为你正在执行dropWhile (=='\n
)`,从字符串的开头删除所有换行符。
要保留空行,您只能删除一个换行符。最简单的方法是使用模式匹配:
getRest = case (dropWhile (/='\n') str) of
(_:xs) -> xs
[] -> []
答案 1 :(得分:2)
如上所述,当你从字符串的开头修剪新的行字符时,你不会得到空行。如果splitLines
被轻微重构,那么看起来会容易得多。由于您无法使用lines
,因此我首先要创建一个简单的split
函数(您也可以使用Data.List.Split):
split :: (Eq a) => a -> [a] -> [[a]]
split a [] = [[]]
split a lst = (\(xs, y:ys) -> [xs] ++ split a ys) $ break (==a) lst
使用此功能,splitLines
很简单:
splitLines :: String -> Document
splitLines [] = []
splitLines str = zip [0..] $ split '\n' str