Search code examples
haskellapplicativetraversable

What is a "applicative transformation" in naturality of traversability?


The traverse and sequenceA function in Traversable class must satisfy the following 'naturality' laws:

t . traverse f == traverse (t . f)
t . sequenceA == sequenceA . fmap t

for every 'applicative transformation' t. But what is it?

It doesn't seem to work for instance Traversable [] for t = tail:

Prelude> tail . sequenceA $ [[1],[2,3]]
[[1,3]]
Prelude> sequenceA . fmap tail $ [[1],[2,3]]
[]

Nor for t = join (++) (repeat the list twice):

Prelude Control.Monad> join (++) . sequenceA $ [[1],[2,3]]
[[1,2],[1,3],[1,2],[1,3]]
Prelude Control.Monad> sequenceA . fmap (join (++)) $ [[1],[2,3]]
[[1,2],[1,3],[1,2],[1,3],[1,2],[1,3],[1,2],[1,3]]

So for what t they are satisfied?


Solution

  • The Hackage page for Data.Traversable defines an applicative transformation as follows.

    [A]n applicative transformation is a function

    t :: (Applicative f, Applicative g) => f a -> g a
    

    preserving the Applicative operations, i.e.

    t (pure x) = pure x
    
    t (x <*> y) = t x <*> t y
    

    The simplest example of this would be the identity function. id is an applicative transformation. A more specific example for lists would be reverse.

    reverse (pure x) = reverse [x] = [x] = pure x
    -- (the (<*>) law is more difficult to show)
    

    And you can verify in GHCi that the laws you reference do hold for reverse.

    Prelude> reverse . sequenceA $ [[1], [2,3]]
    [[1,3],[1,2]]
    Prelude> sequenceA . fmap reverse $ [[1], [2,3]]
    [[1,3],[1,2]]
    

    Source: Data.Traversable