Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the generalisation of unzip?

Most methods I know from lists are actually special cases of some well-known type classes. Some examples of methods and the related type class:

  • map :: (a -> b) -> [a] -> [b] and Functor
  • foldr :: (a -> b -> b) -> b -> [a] -> b and Foldable
  • forM :: Monad m => [a] -> (a -> m b) -> m [b] and Traversable
  • concat :: [[a]] -> [a] and Monad

Possibly the list goes on (pardon the pun).

I'm wondering about the "deeper meaning" behind unzip :: [(a, b)] -> ([a], [b]). Can it be implemented using some famous instances of [] and, e.g., the functor instance of (,a)? Or some other instances? Ideally, I'd want to have a more abstract function with this type: SomeClass m => unzip :: m (a, b) -> (m a, m b). Is there a class that will make this work?

like image 777
Turion Avatar asked Mar 01 '16 10:03

Turion


1 Answers

You can simply take first and second projections:

gunzip :: Functor f => f (a, b) -> (f a, f b)
gunzip ps = (fmap fst ps, fmap snd ps)

But note that gunzip traverses ps twice unlike the usual zip for lists, so it's troublesome, because ps is not garbage collected after the first pass and stays in the memory, which causes memory leaks on big lists.

like image 81
user3237465 Avatar answered Oct 08 '22 12:10

user3237465