Comment déboguer le code Haskell?
J'ai un problème. J'ai écrit un grand programme Haskell, et il fonctionne toujours avec une petite entrée. Maintenant, quand je veux le tester et générer une entrée plus grande, je reçois toujours le message:
HsProg: Prelude.head: empty list
J'utilise Prelude.head
plusieurs fois. Que puis-je faire pour en savoir plus ou obtenir une meilleure sortie d'erreur pour obtenir la ligne de code dans laquelle cela se produit?
2 réponses
L'option GHCi -fbreak-on-exception
peut être utile. Voici un exemple de session de débogage. D'abord, nous chargeons notre fichier dans GHCi.
$ ghci Broken.hs
GHCi, version 7.0.2: http://www.haskell.org/ghc/ :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Loading package ffi-1.0 ... linking ... done.
[1 of 1] Compiling Main ( Broken.hs, interpreted )
Ok, modules loaded: Main.
Maintenant, nous activons -fbreak-on-exceptions
et traçons notre expression (main
dans ce cas pour l'ensemble du programme).
*Main> :set -fbreak-on-exception
*Main> :trace main
Stopped at <exception thrown>
_exception :: e = _
Nous nous sommes arrêtés à une exception. Essayons de regarder le code avec :list
.
[<exception thrown>] *Main> :list
Unable to list source for <exception thrown>
Try :back then :list
Parce que l'exception s'est produite dans Prelude.head
, nous ne pouvons pas regarder la source directement. Mais comme GHCi nous informe, nous pouvons aller :back
et essayer de lister ce qui s'est passé auparavant dans trace.
[<exception thrown>] *Main> :back
Logged breakpoint at Broken.hs:2:23-42
_result :: [Integer]
[-1: Broken.hs:2:23-42] *Main> :list
1
2 main = print $ head $ filter odd [2, 4, 6]
3
Dans le terminal, l'expression incriminée filter odd [2, 4, 6]
est mise en surbrillance en caractères gras. C'est donc l'expression qui a évalué la liste vide dans ce cas.
Pour plus d'informations sur l'utilisation du débogueur GHCi, consultez Le Guide de L'utilisateur GHC.
Vous pouvez jeter un oeil à Haskell Wiki - Debugging, qui contient de nombreuses approches utiles à votre problème.
Un outil prometteur est LocH , ce qui vous aiderait à localiser l'invocation head
dans votre code qui a déclenché l'erreur empty list.
Personnellement, je recommande le paquet safe , qui permet d'annoter la plupart des fonctionspartielles du Prélude (et conduit ainsi à une utilisation plus consciente de ces fonctions partielles les fonctions) ou, mieux encore, utiliser le total variantes de fonctions telles que head
qui retourne toujours un résultat (si la valeur d'entrée est définie, au moins).