7

Despite the jargon filled title I don't think this question is very complex.

Introducing the characters

There are two important Functor combinators at play here. Flip equivalent to the haskell functiong flip but operating on types

newtype Flip p a b
  = Flip
    { unFlip :: p b a
    }

and Join equivalent to the W combinator on types, it takes a bifunctor and produces a functor along both its arguments

newtype Join p a
  = W
    { unW :: p a a
    }

Traversable

Now for Foldable it is possible to make the following instance:

instance
  ( forall a . Foldable (p a)
  , forall a . Foldable (Flip p a)
  )
    => Foldable (Join p) where
  foldr g x (W xs) = foldr g (foldr g x xs) (Flip xs)

That is to say if p is foldable across both of its arguments then Join p is foldable. This is done by folding across the left and then the right.

Now I would like to make an analogous instance for Traversable, however I run into a problem. I can write sequence easily enough

sequence (W xs) = (map W . join . map (sequenceA . unFlip) . sequenceA . Flip) xs

However it seems that I need to be able to use join so I am having trouble writing sequenceA. In fact it very much seems impossible to write a sequenceA.

However I struggle to come up with a counter example. That is a p which is traversable on two arguments but not traversable when joined.

So far I've tried all the basics but none are counter examples. Join (,) is traversable

sequenceA (W (x, y)) = liftA2 (W . (,)) x y

Higher order tuples such as Join ((,,) a) are fine.

sequenceA (W (x, y, z)) = liftA2 (W . (,,) x) y z

Join Either is also traversable

sequenceA (W (Left x)) = map (W . Left) x
sequenceA (W (Right x)) = map (W . Right) x

I've come up with more examples by composing types around, which I will leave out for simplicity but needless to say they all ended up being traversable.

Is there a counter example? Can this instance be written?

Wheat Wizard
  • 3,982
  • 14
  • 34
  • I haven't tried yet, but there is more to `Traversable` than you can "prove" in totally legit Haskell. `lens` does some funny business with a type it calls `Magma`. I stole that idea in a slightly different shape to implement `traverseBia` in `Data.Biapplicative`, and you may find that version useful. So even if it's not possible to do it legitimately, you may well be able to do it through the back door. – dfeuer Aug 23 '20 at 15:10
  • @dfeuer I'm certainly not against backdoor methods but I want to make sure that there isn't a counter example before I use one. I'm not sure I understand what you are meaning when you talk about `traverseBia`. – Wheat Wizard Aug 23 '20 at 15:48
  • I suppose @dfeuer is referring to previous discussions _([one](https://stackoverflow.com/q/48220977/) and [two](https://stackoverflow.com/q/48954495/))_ around `Traversable` where a certain technique was developed of passing through, as I understand, [a free applicative](https://hackage.haskell.org/package/lens-4.19.2/docs/Control-Lens-Internal-Magma.html), which grants you introspection. – Ignat Insarov Sep 13 '20 at 08:52

0 Answers0