Disons que nous avons un algorithme simple arbre dans la création de Haskell:Can Strictness Guide récursion?
data Tree a = EmptyTree | Node a (Tree a) (Tree a) deriving (Show, Read, Eq)
makeTree :: Tree Int -> Tree Int
makeTree (Node 0 l r) = Node 0 EmptyTree EmptyTree
makeTree (Node n l r) = Node n (makeTree $ newTree (n - 1))
(makeTree $ newTree (n - 1))
where
newTree n = Node n EmptyTree EmptyTree
Pour un très grand nombre, nous nous attendons à cet algorithme pour échouer avec une erreur « dépassement de la taille de la pile ». Ce serait parce que l'algorithme est récursif binaire, pas récursif de la queue. Puis-je utiliser des patterns bang (sur la sous-arborescence gauche résultante "! (MakeTree $ newTree (n-1))") pour guider la récursion binaire en récursion de queue, car la récursivité devrait maintenant être dirigée en raison de la rigueur?
EDIT:
Il se trouve que la vraie question est pas la création de l'arbre, mais les fonctions qui consomment de l'arbre. Il y a une autre fonction utilisée pour aplatir l'arbre, où l'instance est la suivante:
import qualified Data.Foldable as F
instance F.Foldable Tree where
foldMap f EmptyTree = mempty
foldMap f (Node x l r) = F.foldMap f l `mappend`
f x `mappend`
F.foldMap f r
flatten = F.foldMap (:[])
L'aplanissement de l'arbre est donc appelé et il est probablement ici où le débordement se produit. Si oui, la solution est-elle aussi simple qu'hypothétiquement la conversion de foldl en foldl '? Ou est-ce que le pliage binaire va ajouter des problèmes supplémentaires?
Huh? Même si cela était strict, ces récursions ne peuvent pas être terminées car un appel de queue doit être la dernière chose qu'une fonction fait. Ici, vous appelez également le constructeur Node après vos deux récursions appelées. – tohava
ce code est incompilable –
Si vous corrigez le code afin qu'il compile, il n'y aura pas de débordement de pile de cette fonction. La paresse aide ... – augustss