The article (and the corresponding passage of the Wikibook) is talking about how the effects (or, to use the language seen there, the contexts) of applicative values can be combined monoidally. The connection with Foldable
is that list-like folding ultimately amounts to combining values monoidally (see chepner's answer, and also Foldr/Foldl for free when Tree is implementing Foldable foldmap?). As for the applicative contexts part, there are a few ways to look at that. One of them is noting that, for any Applicative f
and Monoid m
, f m
is a monoid, with pure mempty
as mempty
and liftA2 mappend
as mappend
(the Ap
type from Data.Monoid
witnesses that). For a concrete example, let's pick f ~ Maybe
and m ~ ()
. That leaves us with four possible combinations:
liftA2 mappend (Just ()) (Just ()) = Just ()
liftA2 mappend (Just ()) Nothing = Nothing
liftA2 mappend Nothing (Just ()) = Nothing
liftA2 mappend Nothing Nothing = Nothing
Now contrast with All
, the Bool
monoid with (&&)
as mappend
:
mappend (All True) (All True) = All True
mappend (All True) (All False) = All False
mappend (All False) (All True) = All False
mappend (All False) (All False) = All False
They match perfectly: Just ()
corresponds to True
, Nothing
to False
, and liftA2 mappend
to (&&)
.
Now let's have another look at the Wikibook example:
deleteIfNegative :: (Num a, Ord a) => a -> Maybe a
deleteIfNegative x = if x < 0 then Nothing else Just x
rejectWithNegatives :: (Num a, Ord a, Traversable t) => t a -> Maybe (t a)
rejectWithNegatives = traverse deleteIfNegative
ghci> rejectWithNegatives [2,4,8]
Just [2,4,8]
ghci> rejectWithNegatives [2,-4,8]
Nothing
The Maybe
values generated by applying deleteIfNegative
to the values in the lists are combined monoidally in the way shown above, so that we get a Nothing
unless all the Maybe
values are Just
.
This matter can also be approached in the opposite direction. Through the Applicative
instance for Const
...
-- I have suppressed a few implementation details from the instance used by GHC.
instance Monoid m => Applicative (Const m) where
pure _ = Const mempty
Const x <*> Const y = Const (x `mappend` y)
... we can get an Applicative
out of any Monoid
, such that (<*>)
combines the monoidal values monoidally. That makes it possible to define foldMap
and friends in terms of traverse
.
On a final note, the category theoretical description of Applicative
as a class for monoidal functors involves something rather different from what I have covered here. For further discussion of this issue, and of other fine print, see Monoidal Functor is Applicative but where is the Monoid typeclass in the definition of Applicative? (if you want to dig deeper, it is well worth it to read all of the answers there).