Vanillo.schnitzel
Vanillo.schnitzel

Reputation: 115

How can I write the following haskell code with higher order functions?

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

Answers (1)

Dogbert
Dogbert

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

Related Questions