snoyberg / mono-traversable

Type classes for mapping, folding, and traversing monomorphic containers
155 stars 64 forks source link

ChunkedData: Why isn't every `Applicative` a `Zip3`, etc? #209

Open ivanbakel opened 2 years ago

ivanbakel commented 2 years ago

Thanks for maintaining the library!

I recently wrote an instance for Zip3 Maybe for a project, and I noticed that the type signatures suggest that every applicative functor could have a valid instance for Zip3 (and vice versa.) There's even a commented-out default implementation for unzip3 in the code that would allow for this instance:

instance Applicative f => Zip3 f where
  zipWith3 f a b c d = f <$> a <*> b <*> c <*> d
  unzip3 = fmap (\(x,_,_)->x) &&& fmap (\(_,x,_)->x) &&& fmap (\(_,_,x)->x)

I vaguely remember reading in the docs somewhere that this instance isn't defined in general because unzip3 would hold 3 references to the original functor value, but I think this could be avoided by using seq to kill some of the thunking. Does it not work that way? Is there another reason to not define this instance (and others for Zip4, etc.?) Would you take a PR that does this?