Так что с рекурсией это довольно просто, не так ли?
import Data.Maybe (isJust)
getBalancedSize :: (Monad m, Num b, Ord b) => BinaryTree a -> m b
getBalancedSize Empty = return 0
getBalancedSize (Node _ l r) = do
sizeL <- getBalancedSize l
sizeR <- getBalancedSize r
if abs (sizeL - sizeR) <= 1
then return $ sizeL + sizeR + 1
else fail "tree is not balanced"
isBalanced :: BinaryTree a -> Bool
isBalanced = isJust . getBalancedSize
Теперь предположим, что у вас есть
fold :: (a -> b -> b -> b) -> b -> Tree a -> b
fold _ b Empty = b
fold f b (Node a l r) = f a (fold f b l) (fold f b r)
Существует очевидный способ реорганизовать getBalancedSize
в один вызов fold
.
getBalancedSize = fold f (return 0) where
f _ l r = do
sizeL <- getBalancedSize l
sizeR <- getBalancedSize r
if abs (sizeL - sizeR) <= 1
then return $ sizeL + sizeR + 1
else fail "tree is not balanced"
Но вам нужна некоторая рекурсивная функция для обхода рекурсивной древовидной структуры.