Reputation: 115
The following code represents a function which takes a list as an input and then combines subsequent repetitions of the same value into a sublist. for example : pack ['a','a','b','b','b','a'] = [['a','a'], ['b','b','b'], ['a']]
pack :: [Char] -> [[Char]]
pack (x:xs) = ys : pack zs
where
(ys, zs) = takeall x (x:xs)
takeall _ [] = ([], [])
takeall x (y:ys)
| x == y = let (us, vs) = takeall x ys
in (y:us, vs)
| otherwise = ([], (y:ys))
I found this code in sample solution. I'm still a beginner at haskell but i've seen the similar problem once as an example for an algorithm in C language.while solving this problem it came to my mind to write the code with the help of higher order functions.I thought the combination of foldl,filter and concatMap could be a good solution for this problem, however i'm not quite sure about filter.I wanted to write a function for filter which goes through the list and compares each element with it's neighbour elements and if they are eqaul returns true. Writing a function like that could be easy but how should i combine it with other functions of higher order so the things that are true come to a list together? How do you solve this problem with higher order functions?
Upvotes: 0
Views: 91
Reputation: 222388
Firstly, your takeall
function can be replaced with the span
function from Prelude:
pack :: [Char] -> [[Char]]
pack (x : xs) = ys : pack zs
where
(ys, zs) = span (== x) (x : xs)
pack [] = []
Then, you can get rid of the explicit recursion using unfoldr
:
import Data.List (unfoldr)
pack2 :: [Char] -> [[Char]]
pack2 = unfoldr go
where
go (x : xs) = Just $ span (== x) (x : xs)
go [] = Nothing
main :: IO ()
main = do
print $ pack ['a', 'a', 'b', 'b', 'b', 'a']
print $ pack2 ['a', 'a', 'b', 'b', 'b', 'a']
Output:
["aa","bbb","a"]
["aa","bbb","a"]
Upvotes: 1