Everywhere I've tried using map
, fmap
has worked as well. Why did the creators of Haskell feel the need for a map
function? Couldn't it just be what is currently known as fmap
and fmap
could be removed from the language?

- 2,377
- 17
- 29

- 17,280
- 20
- 66
- 93
-
13I think you are asking 'What's the point of fmap in Haskell'? – zw324 Jul 26 '11 at 01:19
-
17I know what the point of `fmap` is. It's to map a function over a Functor instance. I'm wondering abou8t the purpose of the specialization to `map`. – Clark Gaebel Jul 26 '11 at 01:38
3 Answers
I would like to make an answer to draw attention to augustss's comment:
That's not actually how it happens. What happened was that the type of map was generalized to cover Functor in Haskell 1.3. I.e., in Haskell 1.3 fmap was called map. This change was then reverted in Haskell 1.4 and fmap was introduced. The reason for this change was pedagogical; when teaching Haskell to beginners the very general type of map made error messages more difficult to understand. In my opinion this wasn't the right way to solve the problem.
Haskell 98 is seen as a step backwards by some Haskellers (including me), previous versions having defined a more abstract and consistent library. Oh well.

- 32,039
- 22
- 142
- 171

- 59,485
- 12
- 145
- 204
-
16Are these backward steps collected and documented anywhere? It would be interesting to see what else was considered a back step and if there are better solutions to them as well. – Davorak Jul 26 '11 at 10:07
-
3The `map and fmap` has been around for a long time - it was reheated on the Haskell-prime mailing list in August 2006 - http://www.haskell.org/pipermail/haskell-prime/2006-August/thread.html. As a counterpoint, I prefer the status quo. To me, it seems valuable that there's a subset of Haskell that corresponds roughly to Miranda. In the UK, Miranda was used as a teaching language for maths students not just computer science students. If that niche isn't already lost to a non-functional language (e.g. Mathematica) I don't see Haskell with a unified `map` filling it. – stephen tetley Jul 26 '11 at 12:32
-
35And I would further like to note, for anyone not already aware, that augustss is Lennart Augustsson, who for all practical purposes has been part of the Haskell community since before Haskell existed, cf. [A History of Haskell](http://research.microsoft.com/en-us/um/people/simonpj/papers/history-of-haskell/index.htm), so the comment in question is not in any way second-hand hearsay! – C. A. McCann Jul 26 '11 at 21:37
-
3There is now [Nitpicks page](https://wiki.haskell.org/Nitpicks) on Haskell wiki where this issue is mentioned. – Alexey Sep 01 '15 at 16:06
-
4It's funny that this decision was made for pedagogical reasons, because I confused fmap with flatmap all the time when learning Haskell. They should have gotten a n00b focusgroup together. :) – Danny Andrews Dec 03 '18 at 16:58
Quoting from the Functor
documentation at https://wiki.haskell.org/Typeclassopedia#Functor
You might ask why we need a separate
map
function. Why not just do away with the current list-onlymap
function, and renamefmap
tomap
instead? Well, that’s a good question. The usual argument is that someone just learning Haskell, when usingmap
incorrectly, would much rather see an error about lists than aboutFunctor
.

- 3,781
- 2
- 30
- 40
They look the same on the application site but they're different, of course. When you apply either of those two functions, map
or fmap
, to a list of values they will produce the same result but that doesn't mean they're meant for the same purpose.
Run a GHCI session (the Glasgow Haskell Compiler Interactive) to query for information about those two functions, then have a look at their implementations and you will discover many differences.
map
Query GHCI for information about map
Prelude> :info map
map :: (a -> b) -> [a] -> [b] -- Defined in ‘GHC.Base’
and you'll see it defined as an high-order function applicable to a list of values of any type a
yielding a list of values of any type b
. Although polymorphic (the a
and b
in the above definition stand for any type) the map
function is intended to be applied to a list of values which is just one possible data type amongst many others in Haskell. The map
function could not be applied to something which is not a list of values.
As you can read from the GHC.Base source code, the map
function is implemented as follows
map _ [] = []
map f (x:xs) = f x : map f xs
which makes use of pattern matching to pull the head (the x
) off the tail (the xs
) of the list, then constructs a new list by using the :
(cons) value constructor so to prepend f x
(read it as "f applied to x") to the recursion of map
over the tail until the list is empty. It's worth noticing that the implementation of the map
function does not rely upon any other function but just on itself.
fmap
Now try to query for information about fmap
and you'll see something quite different.
Prelude> :info fmap
class Functor (f :: * -> *) where
fmap :: (a -> b) -> f a -> f b
...
-- Defined in ‘GHC.Base’
This time fmap
is defined as one of the functions whose implementations must be provided by those data types which wish to belong to the Functor
type class. That means that there can be more than one data types, not only the "list of values" data type, able to provide an implementation for the fmap
function. That makes fmap
applicable to a much larger set of data types: the functors indeed!
As you can read from the GHC.Base source code, a possible implementation of the fmap
function is the one provided by the Maybe
data type:
instance Functor Maybe where
fmap _ Nothing = Nothing
fmap f (Just a) = Just (f a)
and another possible implementation is the one provided by the 2-tuple data type
instance Functor ((,) a) where
fmap f (x,y) = (x, f y)
and another possible implementation is the one provided by the list data type (of course!):
instance Functor [] where
fmap f xs = map f xs
which relies upon the map
function.
Conclusion
The map
function can be applied to nothing more than list of values (where values are of any type) whereas the fmap
function can be applied much more data types: all of those which belongs to the functor class (e.g. maybes, tuples, lists, etc.). Since the "list of values" data type is also a functor (because it provides an implementation for it) then fmap
can be applied to is as well producing the very same result as map
.
map (+3) [1..5]
fmap (+3) (Just 15)
fmap (+3) (5, 7)