liveBook · Manning

Functor

As explained in Functional Design and Architecture: Examples in Haskell

A functor is an abstraction that supports mapping a function over a value while preserving the structure of its context.

A functor maps a function over values while preserving the surrounding data structure. Lists, Maybe values, and domain-specific types can therefore share mapping operations. section 1.3.3 section 6.3.3

Functor behavior appears through a common mapping interface:

  • Mapping can change element types without changing the container structure, such as converting [Int] to [String]. section 6.3.3
  • The fmap operation generalizes list mapping and replaces a simple loop for functional traversal. section 6.3.3
  • Nested functors can be mapped with nested fmap, preserving both layers while transforming their contents. section 1.3.3

Mapping optional values

For [Maybe String], fmap (fmap length) produces [Maybe Int]. Just values become lengths, while Nothing remains Nothing. The outer fmap traverses the list; the inner fmap traverses each Maybe. section 1.3.3

A domain-specific instance

A custom SandwichConstructor type can implement fmap by composing the supplied function with each continuation. Its constructors and stored data remain intact while the continuation result changes. section 6.3.3

import Data.Functor (fmap)
 
-- fmap :: (a -> b) -> [a] -> [b]   #1
 
names :: [String]                   #2
names = ["Alice","Bob", "Trudy"]
 
lengths :: [Int]                    #3
lengths = fmap length names         #4
 
-- lengths: [5,3,5]

A compact list example shows fmap changing names into lengths while retaining list structure. section 1.3.3

Listing 6.3 Functor instance for the free monad
instance Functor SandwichConstructor where              #1
  
  fmap f (StartNewSandwich breadType component next)    #2
    = StartNewSandwich breadType component (f . next)
  
  fmap f (AddComponent component sandwichBody next)
    = AddComponent component sandwichBody (f . next)
  
  fmap f (FinishSandwich mbBreadType sandwichBody next)
    = FinishSandwich mbBreadType sandwichBody (f . next)

A custom instance demonstrates how mapping preserves domain constructors and transforms nested continuations. section 6.3.3

How Functional Design and Architecture: Examples in Haskell covers it

How deep it goes
Defines fmap, demonstrates lists and nested Maybe values, and constructs a custom instance for a domain-specific algebraic type.
Examples
Uses name-length lists, nested Maybe values, integer-to-string mapping, and a SandwichConstructor continuation instance.
What you can do after
Build a Functor instance for a parameterized type and apply fmap across ordinary, nested, and domain-specific structures.
How it connects
Connects functional programming, type classes, algebraic data types, Maybe, monads, and free monads.

Also explained in

Compare how 6 books explain functor →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Functional Design and Architecture: Examples in Haskell. The section links point to the parts of the book it draws on.