Does a joined Bitraversable require Monad?
Asked Answered
C

0

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?

Capsulize answered 23/8, 2020 at 2:55 Comment(3)
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.Sizzle
@Sizzle 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.Capsulize
I suppose @Sizzle is referring to previous discussions (one and two) around Traversable where a certain technique was developed of passing through, as I understand, a free applicative, which grants you introspection.Kaylor

© 2022 - 2024 — McMap. All rights reserved.