We’re by now thoroughly familiar with
the `map`

function, which applies a
function to every element of a list, returning a list of possibly a
different type:

`ghci>`

[2,3,4]`map (+1) [1,2,3]`

`ghci>`

["1","2","3"]`map show [1,2,3]`

`ghci>`

map show :: (Show a) => [a] -> [String]`:type map show`

This `map`

-like activity can be useful in other
instances. For example, consider a binary tree:

-- file: ch10/TreeMap.hs data Tree a = Node (Tree a) (Tree a) | Leaf a deriving (Show)

If we want to take a tree of strings and turn it into a tree containing the lengths of those strings, we could write a function to do this:

-- file: ch10/TreeMap.hs treeLengths (Leaf s) = Leaf (length s) treeLengths (Node l r) = Node (treeLengths l) (treeLengths r)

Now that our eyes are attuned to looking for patterns that we can turn into generally useful functions, we can see a possible case of this here:

-- file: ch10/TreeMap.hs treeMap :: (a -> b) -> Tree a -> Tree b treeMap f (Leaf a) = Leaf (f a) treeMap f (Node l r) = Node (treeMap f l) (treeMap f r)

As we might hope, `treeLengths`

and `treeMap length`

give the same results:

`ghci>`

`let tree = Node (Leaf "foo") (Node (Leaf "x") (Leaf "quux"))`

`ghci>`

Node (Leaf 3) (Node (Leaf 1) (Leaf 4))`treeLengths tree`

`ghci>`

Node (Leaf 3) (Node (Leaf 1) (Leaf 4))`treeMap length tree`

`ghci>`

Node (Leaf True) (Node (Leaf True) (Leaf False))`treeMap (odd . length) tree`

Haskell provides a well-known typeclass to
further generalize `treeMap`

. This
typeclass is named Functor, and it defines ...

Start Free Trial

No credit card required