# Implementing Traversable for Coproduct

Given the following definitions of Functor and Coproduct from fp-course:

class Functor f where
(<$>) :: (a -> b) -> f a -> f b class Functor f => Applicative f where pure :: a -> f a (<*>) :: f (a -> b) -> f a -> f b class Functor t => Traversable t where traverse :: Applicative f => (a -> f b) -> t a -> f (t b) data Coproduct f g a = InL (f a) | InR (g a)  Is there a cleaner or more succinct way to implement the following? instance (Traversable f, Traversable g) => Traversable (Coproduct f g) where traverse :: Applicative h => (a -> h b) -> Coproduct f g a -> h (Coproduct f g b) traverse f (InL fa) = InL <$> traverse f fa
traverse f (InR ga) = InR <\$> traverse f ga


Here is how Edward Kmett implemented traverse in the Data.Functor.Coproduct package.

instance (Traversable f, Traversable g) => Traversable (Coproduct f g) where
traverse f = coproduct
(fmap (Coproduct . Left) . traverse f)
(fmap (Coproduct . Right) . traverse f)


While he writes in a points free style and uses Either under the hood instead of your bespoke Coproduct instance, the result is still the same. Apply the supplied function to either the left or right branch and wrap the result back in the constructor.

I do not see a better way to than the implementation given unless η-conversion to points-free is appealing for some reason.

type Coproduct f g a = Either (f a) (g a) has a Traversal via the lens library:

choosing traverse traverse :: (Traversable tl, Traversable tr, Applicative f)
=> (a -> f b) -> Coproduct tl tr a -> f (Coproduct tl tr b)


I'd expect your usecase to have an easier time using lens directly.