52700.fb2
Развёрткой (unfold) мы получаем из произвольного типа значение данного рекурсивного типа. Мы словно
разворачиваем его из значения, этот процесс очень похож на ленивые вычисления.
Мы узнали некоторые стандартные функции структурной рекурсии: cond или if-выражения, maybe, foldr,
unfoldr.
12.4 Упражнения
• Определите развёртку для деревьев из модуля Data.Tree.
• Определите с помощью свёртки следующие функции:
sum, prod
:: Num a => [a] -> a
or,
and
:: [Bool] -> Bool
length
:: [a] -> Int
cycle
:: [a] -> [a]
unzip
:: [(a,b)] -> ([a],[b])
unzip3
:: [(a,b,c)] -> ([a],[b],[c])
• Определите с помощью развёртки следующие функции:
infinity
:: Nat
map
:: (a -> b) -> [a] -> [b]
iterateTree :: (a -> [a]) -> a -> Tree a
zipTree
:: Tree a -> Tree b -> Tree (a, b)
• Поэкспериментируйте в интерпретаторе с только что определёнными функциями и теми функциями,
что мы определяли в этой главе.
• Рассмотрим ещё один стандартный тип. Он определён в Prelude. Это тип Either (дословно – один из
двух). Этот тип принимает два параметра:
data Either a b = Left a | Right b
Значение может быть либо значением типа a, либо значением типа b. Часто этот тип используют как
Maybe с информацией об ошибке. Конструктор Left хранит сообщение об ошибке, а конструктор Right
значение, если его удалось вычислить.
Например мы можем сделать такие определения:
headSafe :: [a] -> Either String a
headSafe []
= Left ”Empty list”
headSafe (x:_)
= Right x
divSafe :: Fractional a => a -> a -> Either String a
divSafe a 0 = Left ”division by zero”
divSafe a b = Right (a/b)
Для этого типа также определена функция свёртки она называется either. Не подглядывая в Prelude,
определите её.
Краткое содержание | 199
• Список является частным случаем дерева. Список это дерево, в каждом узле которого, лишь однин