map to traverse a list and apply a function to all of its element.
The type signature of
List.map says that it takes two arguments:
a function to use on the elements in a list, and an actual list of elements:
List.map : (a -> b) -> List a -> List b
map function doesn't just exist in the
List module, there are other
maps as well.
Array.map makes sense,
Arrays are basically just lists anyway.
Their type signatures are even almost exactly the same:
Array.map : (a -> b) -> Array a -> Array b
But what about all these other
Maybe.map, what does that do?
Maybe isn't a collection of elements like
Well, it is a collection, but it only contains one element, which might not be there.
Let's look at the type signature of
Maybe.map : (a -> b) -> Maybe a -> Maybe b
Hmm... Strange... That seems awfully familiar.
Anyway, let's try to reason about what this function does!
We start with the last argument 'Maybe a'.
a is lower case, we know that it can be whatever type we want,
as long as the
a is the same in the whole type signature.
The first argument,
(a -> b), is a function that takes an
a and returns a
In other words a function that we can use on the element that might or might not be present in our
Lastly, the return type is
Maybe of the same type that the function
(a -> b) returns.
So what does
Maybe.map actually do?
Maybe in the last argument is a
Nothing we can't really do anything,
map has to return another
Because the type
b be any type,
the implementation of
Maybe.map can't possibly know in advance how to construct that type.
But what if the argument is a
Well, then it's a
Just containing something of type
a, so what do we do with that?
Since the return type of
Maybe.map is a
map has to use the function
(a -> b) on the
a to get a
b, and then wrap it in a
In other words,
Maybe.map takes a function and a
and uses that function on the element in the
Maybe if the element is present.
If we look in the source code for
we see exactly what we expect:
map : (a -> b) -> Maybe a -> Maybe b map f maybe = case maybe of Just value -> Just (f value) Nothing -> Nothing
In fact, if we look at all the other
map functions on other modules,
they all share the same pattern in their type signatures.
They all do what we expect, or what we can guess, by examining their stuctures.
In summary, a the
map function of some structure
Structure looks like this:
Structure.map : (a -> b) -> Structure a -> Structure b
map uses the function provided as its first argument on the element or elements the structure contains.
P.S.: What we here call a structure is called a functor in category theory, and being a functor is one of the requirements of a monad.