**View and edit this tutorial on Github** | Discuss on Reddit | Tweet this

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.

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`

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`

.

(*>) :: 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 :: 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 :: (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_ :: (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_ :: (Foldable t, Applicative f) => t (f a) -> f () sequence_ :: (Foldable t, Monad m) => t (m a) -> m ()

Same `Monad`

/`Applicative`

specialization.

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 :: (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 :: (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.

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

The presence of two different `<>`

operators is purely a historical
accident, caused by the fact that `Semigroup`

is not (yet) a
superclass of `Monoid`

. The functionality for each version of the
operator should be identical. In the case of `Monoid`

, the `<>`

operator is identical to the `mappend`

function.

`++`

is simply `<>`

and `mappend`

specialized to lists.