Pour ce que ça vaut, il y a en fait deux sortes de "débogage" en question ici:
- La journalisation des valeurs intermédiaires, telles que la valeur d'un particulier de la sous-expression a sur chaque appel à une fonction récursive
- Inspecter le comportement d'exécution de l'évaluation d'une expression
Dans un strict impératif de langue coïncident généralement. En Haskell, souvent, ils ne sont pas:
- L'enregistrement des valeurs intermédiaires peuvent modifier le comportement d'exécution, comme en forçant l'évaluation des termes qui seraient autrement jetés.
- Le processus de calcul peuvent considérablement différer de l'apparente la structure d'une expression en raison à la paresse et partagé des sous-expressions.
Si vous voulez garder un journal des valeurs intermédiaires, il existe de nombreuses façons de le faire, par exemple, plutôt que de soulever le tout dans IO
, un simple Writer
monade suffira, cela étant l'équivalent de fonctions de prise de retour d'un 2-tuple de leur résultat réel et un accumulateur de valeur (une sorte de liste de, en général).
Il est aussi généralement pas nécessaire de mettre tout dans la monade, seules les fonctions qui ont besoin d'écrire pour le "journal" de valeur", par exemple, vous pouvez le facteur de la sous-expressions qui pourraient avoir besoin de faire de journalisation, laissant la principale logique pure, puis remonter l'ensemble du calcul en combinant les fonctions pures et la journalisation des calculs de la manière habituelle, avec fmap
s et autres joyeusetés. Gardez à l'esprit que Writer
est une sorte de triste excuse pour un monade: pas moyen de lire à partir du journal, seulement écrire, chaque calcul est logiquement indépendante de son contexte, ce qui rend plus facile de jongler avec les choses autour de vous.
Mais dans certains cas, de même que overkill--pour de nombreuses fonctions pures, simplement en déplaçant les sous-expressions de la racine et en essayant des choses dans le REPL fonctionne assez bien.
Si vous voulez inspecter le temps d'exécution de comportement de code pur, cependant, par exemple, de comprendre pourquoi une sous-expression diverge--il n'y a en général aucun moyen de le faire à partir d'autres code pur--en fait, c'est essentiellement la définition de la pureté. Donc, dans ce cas, vous n'avez pas d'autre choix que d'utiliser les outils qui existent "en dehors" de la pure langue: soit impur fonctions telles que unsafePerformPrintfDebugging
--euh, je veux dire trace
--ou une modification de l'environnement d'exécution, tels que le GHCi débogueur.