There are a number of cases in the `base`

package where the same
functionality exists under two different names. This can occur for a
number of different reasons, but most commonly it's either:

- One version is more general than the other via some typeclass
- A historical name has lingered on

The presence of identical (or nearly identical) functionality under different names can lead to confusion when reading code. The purpose of this page is to point out these occurrences to bypass this confusion.

## concat, mconcat and fold

GHC.OldList.concat :: [[a]] -> [a] Prelude.concat :: Foldable t => t [a] -> [a] mconcat :: Monoid a => [a] -> a fold :: (Foldable t, Monoid a) => t a -> a

All four of these functions allow us to collapse down a sequence of
values into a single value. The most specific is `GHC.OldList.concat`

:
given a list of lists, it combines all of these lists together into a
single list. The most general is `fold`

, which leverages two
typeclasses:

- Instead of requiring that the containers be a list, it leverages the
`Foldable`

typeclass to work with many more data structures - Instead of requiring that the values being combined be lists, it
generalizes to any instance of
`Monoid`

## concatMap and foldMap

GHC.OldList.concatMap :: (a -> [b]) -> [a] -> [b] Prelude.concatMap :: Foldable t => (a -> [b]) -> t a -> [b] foldMap :: (Foldable t, Monoid b) => (a -> b) -> t a -> b

This is very similar to the `concat`

/`mconcat`

/`fold`

breakdown
above. We can generalize from lists to instances of `Foldable`

and
`Monoid`

.

## *> and >>

(*>) :: Applicative f => f a -> f b -> f b (>>) :: Monad m => m a -> m b -> m b

The only difference between these two is `Applicative`

vs
`Monad`

. This is a holdover from the days when `Applicative`

was not a
superclass of `Monad`

.

## pure and return

pure :: Applicative f => a -> f a return :: Monad m => a -> m a

`return`

is `pure`

specialized to `Monad`

, relevant for the same
superclass reason above.

## map, fmap and liftM

map :: (a -> b) -> [a] -> [b] fmap :: Functor f => (a -> b) -> f a -> f b liftM :: (Monad m) => (a -> b) -> m a -> m b

`map`

is specialized to just lists, while `fmap`

is generalized to all
`Functor`

s. Like `*>`

vs `>>`

, the presence of `liftM`

is just a
holdover from the days when `Functor`

was not a superclass of `Monad`

.

## traverse_ and mapM_

traverse_ :: (Foldable t, Applicative f) => (a -> f b) -> t a -> f () mapM_ :: (Foldable t, Monad m) => (a -> m b) -> t a -> m ()

`mapM_`

is `traverse_`

specialized to `Monad`

, relevant for the same
superclass reason above.

## sequenceA_ and sequence_

sequenceA_ :: (Foldable t, Applicative f) => t (f a) -> f () sequence_ :: (Foldable t, Monad m) => t (m a) -> m ()

Same `Monad`

/`Applicative`

specialization.

## traverse and mapM

traverse :: (Traversable t, Applicative f) => (a -> f b) -> t a -> f (t b) mapM :: (Traversable t, Monad m) => (a -> m b) -> t a -> m (t b)

Same `Monad`

/`Applicative`

specialization.

## sequenceA and sequence

sequenceA :: (Traversable t, Applicative f) => t (f a) -> f (t a) sequence :: (Traversable t, Monad m) => t (m a) -> m (t a)

Same `Monad`

/`Applicative`

specialization.

## for and forM

for :: (Traversable t, Applicative f) => t a -> (a -> f b) -> f (t b) forM :: (Traversable t, Monad m) => t a -> (a -> m b) -> m (t b)

Same `Monad`

/`Applicative`

specialization.

## <>, ++ and mappend

(++) :: [a] -> [a] -> [a] Data.Semigroup.(<>) :: Semigroup a => a -> a -> a mappend :: Monoid m => m -> m -> m

`++`

is simply `<>`

and `mappend`

specialized to lists. `mappend`

should be the
same as `<>`

in all cases.

Note: historically, `Semigroup`

was not a superclass of `Monoid`

, resulting in
`<>`

and `mappend`

having potentially different implementations. That no longer
applies.