I've accidently written a

Haskell Functors Tutorial

I'll answer your question using examples, and I'll put the types underneath in comments.

Watch out for the pattern in the types.

fmap is a generalisation of map

Functors are for giving you the fmap function. fmap works like map , so let's check out map first:

map (subtract 1) [2,4,8,16] = [1,3,7,15] -- Int->Int [Int] [Int]

So it uses the function (subtract 1) inside the list. In fact, for lists, fmap does exactly what map does. Let's multiply everything by 10 this time:

fmap (* 10) [2,4,8,16] = [20,40,80,160] -- Int->Int [Int] [Int]

I'd describe this as mapping the function that multiplies by 10 over the list.

fmap also works on Maybe

What else can I fmap over? Let's use the Maybe data type, which has two types of values, Nothing and Just x . (You can use Nothing to represent a failure to get an answer while Just x represents an answer.)

fmap (+7) (Just 10) = Just 17 fmap (+7) Nothing = Nothing -- Int->Int Maybe Int Maybe Int

OK, so again, fmap is using (+7) inside the Maybe. And we can fmap other functions too. length finds the length of a list, so we can fmap it over Maybe [Double]

fmap length Nothing = Nothing fmap length (Just [5.0, 4.0, 3.0, 2.0, 1.573458]) = Just 5 -- [Double]->Int Maybe [Double] Maybe Int

Actually length :: [a] -> Int but I'm using it here on [Double] so I specialised it.

Let's use show to turn stuff into strings. Secretly the actual type of show is Show a => a -> String , but that's a bit long, and I'm using it here on an Int , so it specialises to Int -> String .

fmap show (Just 12) = Just "12" fmap show Nothing = Nothing -- Int->String Maybe Int Maybe String

also, looking back to lists

fmap show [3,4,5] = ["3", "4", "5"] -- Int->String [Int] [String]

fmap works on Either something

Let's use it on a slightly different structure, Either . Values of type Either a b are either Left a values or Right b values. Sometimes we use Either to represent a success Right goodvalue or failure Left errordetails , and sometime just to mix together values of two types into one. Anyway, the functor for the Either data type only works on the Right - it leaves Left values alone. That makes sense particularly if you're using Right values as the successful ones (and in fact we wouldn't be able to make it work on both because the types aren't necessarily the same). Lets use the type Either String Int as an example

fmap (5*) (Left "hi") = Left "hi" fmap (5*) (Right 4) = Right 20 -- Int->Int Either String Int Either String Int

It makes (5*) work inside the Either, but for Eithers, only the Right values get changed. But we can do it the other way round on Either Int String , as long as the function works on strings. Let's put ", cool!" at the end of stuff, using (++ ", cool!") .

fmap (++ ", cool!") (Left 4) = Left 4 fmap (++ ", cool!") (Right "fmap edits values") = Right "fmap edits values, cool!" -- String->String Either Int String Either Int String

It's especially cool to use fmap on IO

Now one of my favourite ways of using fmap is to use it on IO values to edit the value some IO operation gives me. Let's make an example that lets you type something in and then prints it out straight away:

echo1 :: IO () echo1 = do putStrLn "Say something!" whattheysaid <- getLine -- getLine :: IO String putStrLn whattheysaid -- putStrLn :: String -> IO ()

We can write that in a way that feels neater to me:

echo2 :: IO () echo2 = putStrLn "Say something" >> getLine >>= putStrLn

>> does one thing after another, but the reason I like this is because >>= takes the String that getLine gave us and feeds it to putStrLn which takes a String. What if we wanted to just greet the user:

greet1 :: IO () greet1 = do putStrLn "What's your name?" name <- getLine putStrLn ("Hello, " ++ name)

If we wanted to write that in the neater way I'm a bit stuck. I'd have to write

greet2 :: IO () greet2 = putStrLn "What's your name?" >> getLine >>= (

ame -> putStrLn ("Hello, " ++ name))

which is not nicer than the do version. In fact the do notation is there so you don't have to do this. But can fmap come to the rescue? Yes it can. ("Hello, "++) is a function that I can fmap over the getLine!

fmap ("Hello, " ++) getLine = -- read a line, return "Hello, " in front of it -- String->String IO String IO String

we can use it like this:

greet3 :: IO () greet3 = putStrLn "What's your name?" >> fmap ("Hello, "++) getLine >>= putStrLn

We can pull this trick on anything we're given. Let's disagree with whether "True" or "False" was typed in:

fmap not readLn = -- read a line that has a Bool on it, change it -- Bool->Bool IO Bool IO Bool

Or let's just report the size of a file:

fmap length (readFile "test.txt") = -- read the file, return its length -- String->Int IO String IO Int -- [a]->Int IO [Char] IO Int (more precisely)

Conclusions: What does fmap do, and what does it do it to?

If you've been watching the patterns in the types and thinking about the examples you'll have noticed that fmap takes a function that works on some values, and applies that function on something that has or produces those values somehow, editing the values. (eg readLn was to read Bool, so had type IO Bool there's a Boolean value in it in the sense that it produces a Bool , eg2 [4,5,6] has Int s in it.)

fmap :: (a -> b) -> Something a -> Something b

this works for Something being List-of (written [] ), Maybe , Either String , Either Int , IO and loads of over things. We call it a Functor if this works in a sensible way (there are some rules - later). The actual type of fmap is

fmap :: Functor something => (a -> b) -> something a -> something b

but we usually replace something with f for brevity. It's all the same to the compiler, though:

fmap :: Functor f => (a -> b) -> f a -> f b

Have a look back at the types and check this always works - think about Either String Int carefully - what's f that time?

Appendix: What are the Functor rules, and why do we have them?

id is the identity function:

id :: a -> a id x = x

Here are the rules:

fmap id == id -- identity identity fmap (f . g) == fmap f . fmap g -- composition

Firstly the identity identity: If you map the function that does nothing, that doesn't change anything. That sounds obvious (a lot of rules do), but you can interpret that as saying that fmap is only allowed to change the values, not the structure. fmap isn't allowed to turn Just 4 into Nothing , or [6] into [1,2,3,6] , or Right 4 into Left 4 because more than just the data changed - the structure or context for that data changed.

I hit this rule once when I was working on a graphical user interface project - I wanted to be able to edit the values, but I couldn't do it without changing the structure underneath. No-one would have really noticed the difference because it had the same effect, but realising it didn't obey the functor rules made me rethink my whole design, and it's much cleaner, slicker and faster now.

Secondly the composition: this means you can choose whether to fmap one function at a time, or fmap them both at the same time. If fmap leaves the structure/context of your values alone and just edits them with the function its given, it will work with this rule too.

There's a secret third rule that mathematicians have, but we don't call it a rule in Haskell, because it just looks like a type declaration:

fmap :: (a -> b) -> something a -> something b

This one stops you from applying the function to just the first value in your list, for example. This law is enforced by the compiler.

Why do we have them? To make sure fmap doesn't sneakily do anything behind the scenes or change anything we didn't expect. They're not enforced by the compiler (asking the compiler to prove a theorem before it compiles your code isn't fair, and would slow compilation down - the programmer should check). This means you can cheat the laws a bit, but that's a bad plan because your code can give unexpected results.