Data.List.NonEmpty.map and .fmap

As I continue to look at base and Data.List.NonEmpty this other question has occurred to me:

Data.List.NonEmpty.NonEmpty is, ultimately, a re-export from ghc-internal of GHC.Internal.Base.NonEmpty, which module also defines an instance of Functor:

-- | @since base-4.9.0.0
instance Functor NonEmpty where
  fmap f ~(a :| as) = f a :| fmap f as
  b <$ ~(_ :| as)   = b   :| (b <$ as)

Data.List.NonEmpty exports map, defined as:

-- | Map a function over a 'NonEmpty' stream.
map :: (a -> b) -> NonEmpty a -> NonEmpty b
map f ~(a :| as) = f a :| fmap f as

This is the question: would it be better for Data.List.NonEmpty.map to be:

map :: (a -> b) -> NonEmpty a -> NonEmpty b
map = fmap
3 Likes

I think you’re absolutely right!

There might be a reason related to (better) inlining or specialization for having written out the map implementation explicitly, but it seems more likely that it just happened for historical reasons (e.g. the map implementation was there first and the Functor instance was added more recently).

2 Likes

Yeah, I think we should do that.

1 Like