Идея функции foldBT
заключается в том, что она принимает аргумент для каждого конструктора вашего типа данных (плюс тот, который содержит весь SimpleBT a
, который вы хотите свернуть).Первый тип a -> b -> b -> b
соответствует рекурсивному конструктору N
и показывает, как объединить значение в узле с результатами сгиба двух поддеревьев в результат всего сгиба.Второй аргумент соответствует конструктору Nil
, и поскольку этот конструктор не принимает аргументов, соответствующий аргумент fold
является просто константой.
Это абсолютно аналогично сворачиванию списка.Тип списка [a]
также имеет 2 конструктора.Один из них берет a
и список и добавляет элемент в начало списка: a -> [a] -> [a]
, это приводит к «функции сгиба» типа a -> b -> b
.Другой конструктор, как и в вашем случае, является нулевым (пустой список), поэтому снова соответствует аргументу, тип которого просто b
.Следовательно, foldr
для списка имеет тип (a -> b -> b) -> b -> [a] -> b
.
В этой главе вики-книги Haskell есть большое обсуждение этого, с большим количеством примеров: https://en.wikibooks.org/wiki/Haskell/Other_data_structures
Что касаетсякак построить карту из сгиба, для вашего конкретного типа дерева - учитывая то, что я сказал выше, вам нужно (учитывая функцию отображения f :: a -> a0
), нам нужно подумать о том, что это делает с Nil
дерево, и что оно делает рекурсивно для деревьев с листом и 2 ветками.Кроме того, поскольку наш тип возврата, конечно, будет другим деревом того же типа, b
здесь будет SimpleBT a0
.
Для Nil
, очевидно, мы хотим, чтобы map
оставил его без изменений, поэтомувторой аргумент foldBT
будет Nil
.А для другого конструктора мы хотим, чтобы map
применил базовую функцию к значению на листе, а затем рекурсивно отобразил 2 ветви.Это приводит нас к функции \a left right -> N (f a) (mapTree f left) (mapTree f right)
.
. Таким образом, мы можем заключить, что функцию карты можно определить следующим образом (спасибо @DanielWagner и @WillemVanOnsen за помощь в исправлении моей первой сломанной версии):
mapTree :: (a -> b) -> SimpleBT a -> SimpleBT b
mapTree f = foldBT foldFunc Nil
where foldFunc a l r = N (f a) l r