What the f-unctor?

All over the map(s)

Where we learn that map is not just for lists (and about a forbidden f-word)

Michel Belleville
Wat, the Elm-ist
Published in
4 min readFeb 10, 2019

--

me> Wat?

wat> Hmm?

me> Remember we talked about Maybe? And you showed me this Maybe.map function to take what’s in it so we can work with it (and just continue when there’s nothing)?

wat> Sure ; what about it?

me> Is there a reason why I find map also in Array, List, …

wat> There is 😃 look at their signature:

Maybe.map : (a -> b) -> Maybe a -> Maybe b
List.map : (a -> b) -> List a -> List b
Array.map : (a -> b) -> Array a -> Array b

me> 😮 They look all the same! It’s like:

Something.map : (a -> b) -> Something a -> Something b

wat> 👏 looks like there is a pattern indeed (and you can see in every package that has a map function that it’s a general trend). What do you think?

me> So… it’s like all of these are data structures that have something inside and their map function allows you to take what’s inside and apply a function, re-packaging the result into the structure… but a Maybe, a List or an Array don’t necessarily have something inside… and a List and an Array may hold many things inside.

wat> That’s why they each have their own map functions. Maybe.map knows how to take what is inside the Maybe (if anything) and how to repack the new value into a Just, or else that it needs to return Nothing. List.map and Array.map know how to iterate on each element, and repackage all the new values in the same order.

me> Ok… so map is a kind of generic name for “take what’s inside and apply a transformation, and repackage the results into the structure”?

wat> Kiiiiiind of… consider Generator

me> What’s a Generator?

wat> It’s a type that we can use to get a value randomly generated. You can look at it like a deck of cards or a set of dice that can pick anything you want at random. We’re not going to discuss how to use it (yet) ; for our purpose today, if you’ve got a Generator a, you have some kind of promise that when you use it you’ll get an a each time.

me> Ooooook. So, a Generator a is like having an a in the future?

wat> Precisely. And Generator has its map function too! Can you guess its signature?

me> Hmm…

Generator.map : (a -> b) -> Generator a -> Generator b

me> Is that the Generator.map you’re looking for?

wat> 😄

me> Soooo… aside from the increasingly familiar a -> b transformation function, it takes our Generator a that can produce values of type a and give us back a Generator b that can produce values of type b… but… how can it transform a future value?

wat> That’s the trick the people who invented the Generator type figured out for you 😉 (you can look at the function’s source if you want to know how they did it) ; what I wanted you to see is that map does not necessarily need for something to be “inside” the type it works with. It can be something that’s “promised” too. And it’s not just Generator:

Cmd.map : (a -> b) -> Cmd a -> Cmd b
Sub.map : (a -> b) -> Sub a -> Sub b
Html.map : (a -> b) -> Html a -> Html b

wat> A Cmd a is a command that may produce messages of type a, a Sub a is a subscription to events that might produce messages of type a and an Html a is a structure that represents an html dom tree that can (🎉 surprise!) produce messages of type a

me> And their map function allows you to change the messages they produce from a type a into new messages of type b? Just like Generator.map?

wat> Yep 😃 there is even a word for those types that have a map function…

me> Ooook. What is it?

wat> *mumbles unintelligibly something about the f-word*

me> What, *that* f-word? 🍆

wat> Nah. Worse. A word so terrifying that the Elm creators dared not have it spoken aloud, in fear that the coding masses flee their creation.

me> Oh, come on wat, it will stay between us.

wat> It’s Functor.

me> Func-what?

wat> Functor. I know, I know, it sounds like a made-up word (which it is (like any other word, really)). It’s one of those words mathematicians and computer scientists love to invent. But when you read or hear it, you can almost always replace it mentally by “that which can be map-ed upon”.

me> So, that’s all it means? Something that has a map function for?

wat> Almost. To be a well-behaved Functor, you must abide by some rules ; I’ll let you discover them by yourself if you like, but beware: they often are expressed in terms specific to category theory, so you might want to get the gist of that first. And anyways, you most probably won’t need to know them on a daily basis to guess what a map function does, nor to use it proficiently.

me> Why would I need them then?

wat> They may be useful when you create a map on a custom data type, and don’t want to end up with something too wonky.

me> Ok. Well, I guess that’ll be enough for now…

wat> Quack to you soon 🦆

--

--