Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Haskell understanding flow

Tags:

haskell

I'm new to haskell, I was trying to write a string split function

delim = '|'
splitStr::[Char]->[[Char]]->[[Char]]
splitStr list y                 
                | sL > 0 && sL < length(list) = splitStr (drop (sL+1) list) [subList]++y
                | otherwise = [subList]++y
                where 
                    subList = takeWhile (\x -> x /= delim) list 
                    sL = length(subList)

split s = splitStr s []

However, the above code always returns the String in reverse order

Main> split "foo|bar|java|python"
["python","java","bar","foo"]

changing from y++[subList] to [subList]++y still gives the same result. I know there maybe better ways to do it, but I want to know why the above is happening.

like image 567
Rnet Avatar asked Mar 29 '11 18:03

Rnet


2 Answers

splitStr (drop (sL+1) list) [subList]++y

This is parsed as (splitStr (drop (sL+1) list) [subList])++y. What you wanted is probably splitStr (drop (sL+1) list) ([subList]++y).

like image 197
sepp2k Avatar answered Nov 19 '22 14:11

sepp2k


Here is, additional to what sepp2k said, something about how to improve your code:

In your code you don't need an accumulator, since you can exploit the codes laziness. I rewrote your code like I would do it:

split :: Char -> String -> [String]
split delim "" = []
split delim s  = chunk : split delim rest where
 (chunk,_:rest) = break (==delim) s

How does it works? I split the string at the first char, that is equal to the delimiter. I return that part and call the function recursivly onto the rest of the list. This is very efficient, since Haskell won't evaluate the rest of the list until it's needed.

like image 37
fuz Avatar answered Nov 19 '22 13:11

fuz