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:
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:
Foldable
typeclass to work with many more data structuresMonoid
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
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.