Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Haskell pair and unpair functions

I have the following two functions written.

pair :: [a] -> [(a, a)]
pair [] = []
pair [x] = []
pair (x1:x2:xs) = (x1, x2) : pair xs

unpair :: [(a, a)] -> [a]
unpair [] = []
unpair ((x1, x2):xs) = x1 : x2 : unpair xs

Pair will take pairs of elements and make 2-tuples of them. If the list has an odd number of elements, discard the last one. Unpair is the reverse of pair.

These work, but wondering whether there is a more succinct way to write these.

like image 642
qrest Avatar asked Jul 16 '10 15:07

qrest


2 Answers

One-liners:

pair xs = map snd . filter fst . zip (iterate not True) $ zip xs (drop 1 xs)
unpair = concatMap (\(x,y) -> [x,y])

You could have also abbreviate your definition of pair a little:

pair (x1:x2:xs) = (x1, x2) : pair xs
pair _ = []
like image 152
sastanin Avatar answered Sep 28 '22 06:09

sastanin


It's not any more concise, but for the sake of clarity I'd use splitEvery from Data.List.Split for pair:

pair = map tuplify . filter ((>1) . length) . splitEvery 2
  where
    tuplify [x, y] = (x, y)

This is off the top of my head—it would be nicer to check the length of the last list only.

For unpair I'd use foldr to avoid the explicit recursion:

unpair = foldr (\(x, y) -> (x:) . (y:)) []

This is just a matter of taste.

like image 20
Travis Brown Avatar answered Sep 28 '22 05:09

Travis Brown