Деревья тоже являются функторами
Ещё один тип, который можно отображать и сделать для него экземпляр класса Functor, – это наш тип Tree. Дерево может хранить ноль или более других элементов, и конструктор типа Tree принимает один тип-параметр. Если бы мы хотели записать функцию fmap только для типа Tree, её сигнатура выглядела бы так: (a –> b) –> Tree a –> Tree b.
Для этой функции нам потребуется рекурсия. Отображение пустого дерева возвращает пустое дерево. Отображение непустого дерева – это дерево, состоящее из результата применения функции к корневому элементу и из правого и левого поддеревьев, к которым также было применено отображение.
instance Functor Tree where
fmap f EmptyTree = EmptyTree
fmap f (Node x left right) = Node (f x) (fmap f left) (fmap f right)
Проверим:
ghci> fmap (*2) EmptyTree
EmptyTree
ghci> fmap (*4) (foldr treeInsert EmptyTree [5,7,3])
Node 20 (Node 12 EmptyTree EmptyTree) (Node 28 EmptyTree EmptyTree)
Впрочем, тут следует быть внимательным! Если тип Tree используется для представления бинарного дерева поиска, то нет никакой гарантии, что дерево останется таковым после применения к каждому его узлу некоторой функции. Проход по дереву функцией, скажем, negate превратит дерево поиска в обычное дерево.