Skip to content

Haskell Functors Guide — fmap, (<$>), and the Functor Typeclass

DodaTech Updated 2026-06-28 3 min read

In this tutorial, you will learn about Haskell Functors Guide. We cover key concepts, practical examples, and best practices to help you master this topic.

Haskell Functor is a typeclass with fmap (or infix <$>) that applies a function to a value wrapped in a context -- enabling map-like operations on Maybe, Either, lists, IO, and any type with a lawful fmap implementation.

Functor Typeclass

class Functor f where
    fmap :: (a -> b) -> f a -> f b
    -- (<$>) = fmap as infix operator

-- Laws:
-- fmap id = id
-- fmap (f . g) = fmap f . fmap g

Maybe and Either

-- Maybe Functor
fmap (*2) (Just 5)     -- Just 10
fmap (*2) Nothing      -- Nothing
(*2) <$> Just 5        -- Just 10

-- Either Functor
fmap length (Right "hello")  -- Right 5
fmap length (Left "error")   -- Left "error"

-- Chaining
process = fmap (+1) . fmap (*2)
process (Just 5)  -- Just 11

List Functor

-- Lists are Functors
fmap (*2) [1,2,3]    -- [2,4,6] (same as map)

-- Function composition with lists
process = fmap (+1) . fmap (*2)
process [1,2,3]       -- [3,5,7]

-- Nested functors
fmap (fmap (*2)) [[1,2],[3]]  -- [[2,4],[6]]

IO Functor

-- IO is a Functor
getLength = fmap length getLine
-- Or:
getLength = length <$> getLine

-- Combining IO and pure
greet = do
    name <- fmap (++ "!") getLine
    putStrLn $ "Hello, " ++ name

-- (++) "Hello," <$> getLine

Custom Functor

data Box a = Box a deriving Show

instance Functor Box where
    fmap f (Box x) = Box (f x)

fmap (*3) (Box 10)  -- Box 30

-- Tree Functor
data Tree a = Leaf a | Branch (Tree a) (Tree a)

instance Functor Tree where
    fmap f (Leaf x)       = Leaf (f x)
    fmap f (Branch l r)   = Branch (fmap f l) (fmap f r)

Common Mistakes

1. Expecting fmap to work on non-Functor types

fmap only works on types that implement the Functor typeclass. Lists, Maybe, Either, IO all do.

2. Violating Functor laws

fmap id must equal id. fmap (f . g) must equal fmap f . fmap g. Breaking these causes confusing behavior.

3. Confusing fmap with bind (>>=)

fmap applies a pure function. bind (>>=) applies a function that returns a monadic value.

Practice Questions

1. What does fmap (+1) (Just 5) return? Just 6. fmap applies the function inside the Maybe context.

2. What is the infix version of fmap? (<$>). (+1) <$> Just 5 is equivalent to fmap (+1) (Just 5).

3. Can IO be a Functor? Yes. fmap length getLine returns an IO Int that reads a line and returns its length.

FAQ

{{< faq question="What are the Functor laws?" >}} Identity: fmap id = id. Composition: fmap (f . g) = fmap f . fmap g. These ensure fmap behaves predictably. {{< /faq >}}

{{< faq question="Is fmap for lists the same as map?" >}} Yes, fmap on lists is exactly map. In fact, map = fmap for historical reasons. {{< /faq >}}

{{< faq question="What is the difference between Functor and Applicative?" >}} Functor applies a pure function to a wrapped value. Applicative applies a wrapped function to a wrapped value. {{< /faq >}}

What's Next

Now learn about applicative functors.

Topic Description Link
Applicatives Applicative functors {{< ref "10-applicatives" >}}
Monads Monads and do notation {{< ref "11-monads" >}}

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro