views:

109

answers:

2

So have this

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))

works ok except i guess i need empty lines as well.

splitLines "test\nthis\nstring\n" should be
[(0,"test"),(1,"this"),(2,"string"),(3,"")]

Not exactly sure how i could do this. Any ideas? Do i need to rewrite it with something else?

Should i use a high order function like foldr? Thanks.

Figured it out finally thanks.

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)
+2  A: 

It's discarding the empty lines because you're doing dropWhile (=='\n)`, removing all linebreaks from the beginning of the string.

To keep the empty lines, you must only drop one linebreak. The easiest way to do that is to use pattern matching:

getRest = case (dropWhile (/='\n') str) of
              (_:xs) -> xs
              [] -> []
sepp2k
+1  A: 

As mentioned, you don't get the empty lines as you are trimming the new line character off of the start of the string. It would be a lot easier to see this if splitLines was refactored slightly. Since you cannot use lines it I would start by creating a simple split function (you could also use Data.List.Split):

split :: (Eq a) => a -> [a] -> [[a]]
split a [] = [[]]
split a lst = (\(xs, y:ys) -> [xs] ++ split a ys) $ break (==a) lst

With this function, splitLines is simple:

splitLines :: String -> Document
splitLines [] = []
splitLines str = zip [0..] $ split '\n' str 
Paul
honestly i don't even think i can use split and break. But i did finally get it. Thanks.
Matt