Учитывая дерево, которое выглядит так:
data Tree a = Leaf | Node (Tree a) a (Tree a)
И функцию сгиба, которая выглядит следующим образом:
foldTree :: (b -> a -> b -> b) -> b -> Tree a -> b
foldTree _ b Leaf = b
foldTree fn b (Node lt x rt) = f (foldTree fn b lt) x (foldTree fn b rt)
Я хочу иметь возможность написать функцию takeWhileTree, которая выглядитнапример:
treeTakeWhile :: (a -> Bool) -> Tree a -> Tree a
Я хочу, чтобы она имитировала функцию takeWhile 'обычного' списка, чтобы она возвращала максимально возможное дерево, элементы которого удовлетворяют данному условию.
Итак, если деревоt = Node (Node Leaf 10 Leaf) 4 (Node Leaf 5 Leaf)
, затем:
treeTakeWhile (> 5) T = Leaf
treeTakeWhile (>= 4) T = T
treeTakeWhile (< 5) T = Node Leaf 4 Leaf
treeTakeWHile (< 8) T = Node Leaf 4 (Node Leaf 5 Leaf)
Пока что я, похоже, не могу сформулировать, что передать в foldTree.В определении foldtree функция может быть разбита следующим образом: b, вероятно, является левым поддеревом, a, вероятно, является значением в текущем узле, а b, вероятно, является правым поддеревом.
Следовательно, функция переданаtreeTakeWhile должен быть применен ко всем этим частям узла каким-либо образом, чтобы иметь возможность остановиться, когда операция больше не применяется.
treeTakeWhile fn = foldTree (\xs x ys -> if y then g else Leaf) Node()
where g = (lt, x, rt)
y = fn (Node lt x rt)
Выше явно неверно, но я не уверен, как выразитьакт применения функции к значению текущего узла, за которым следуют левое дерево и правое дерево.Может ли кто-нибудь указать мне правильное направление?И как фолд сможет создать требуемое дерево?
Редактировать 1:
Хорошо, основываясь на ваших отзывах, я попал в такое место, где я думаю, что я довольно близок кответить, но не могу понять, почему компилятор все еще жалуется:
treeTakeWhile :: (a -> Bool) -> Tree a -> Tree a
treeTakeWhile c = foldTree f acc
where acc = Leaf
f l x r = if c x then Node (f lt) x (f rt) else Leaf
Насколько я могу судить, foldTree сейчас передаются правильные аргументы.И предикат также оценивается по мере необходимости на каждом уровне дерева.Возвращаемое значение также всегда имеет тип Tree.