I was needing a way to zip generic data structures together today and was very annoyed to find that there is no Zippable class, or variant there of.<br><br>So I made my own:<br><br>class (Foldable f, Functor f) => Zippable f where<br>
fmaps :: (Foldable g) => g (a -> b) -> f a -> f b<br> fmaps' :: [a -> b] -> f a -> f b -- to save a step on instance implementation<br> zipWith :: (a -> b -> c) -> f a -> f b -> f c<br>
zip :: f a -> f b -> f (a, b)<br> unzip :: f (a, b) -> (f a, f b)<br> <br> fmaps fs a = fmaps' (toList fs) a<br> fmaps' fs a = fmaps fs a<br> zipWith f a b = fmaps (fmap f a) b<br> zip = zipWith (,)<br>
unzip a = (fmap fst a, fmap snd a) <br> <br>instance Zippable [] where<br> fmaps' (fx:fs) (x:xs) = fx x : fmaps' fs xs<br> fmaps' _ _ = []<br> <br>--The fmaps function is also quite handy as a replacment for zipWith3, zipWith4, etc...<br>
--For example:<br> <br>x = [1, 3, 5, 7, 3]<br>y = [6, 9, 3, 1, 4]<br>z = [2, 4, 0, 8, 2]<br>test = fmap (,,) x `fmaps` y `fmaps` z<br>-- > [(1,6,2),(3,9,4),(5,3,0),(7,1,8),(3,4,2)]<br><br>--you can also throw in a functor instance to remove the dependency on the Functor class, but it <br>
-- might not be worth it:<br>instance (Zippable f) => Functor f where<br> fmap f a = fmaps (repeat f) a<br><br><br>Is there any good reason that there isn't something like this in the standard libraries? Or, as far as I can tell, on hackage?<br>
If not, then maybe I'll stick it on hackage.<br><br>- Job Vranish<br><br><br>