Tout d'abord, un rapide avertissement: "enregistrement" n'a pas l'habitude de faire du sentiment en général du code Haskell, car il suppose une certaine sorte de l'exécution séquentielle qui peuvent ou peuvent ne pas être significatifs. Assurez-vous que vous faites une distinction entre la journalisation de la façon dont le programme s'exécute et la journalisation à ce que les valeurs sont calculées. Dans le strict impératif langues, ces sont essentiellement les mêmes, mais en Haskell ils ne le sont pas.
Cela dit, il semble que vous souhaitez ouvrir une session basée sur les valeurs étant calculées, dans le contexte d'une déjà séquentielle et stateful de calcul, qui réussit plutôt bien le même que l'exploitation forestière dans la plupart des autres langues. Cependant, vous avez besoin de la monade à l'appui de certains moyens de le faire. Il ressemble à l'analyseur que vous utilisez est de la HCodecs paquet, ce qui semble être relativement limitée, n'autorise pas l' IO
, et n'est pas défini comme une monade transformateur.
Honnêtement, mon conseil serait d'envisager d'utiliser une autre analyse de la bibliothèque. Parsec a tendance à être le choix par défaut, et je pense que attoparsec est populaire à des fins spécifiques (qui pourrait comprendre ce que vous faites). L'un et l'autre vous permettent d'ajouter de journalisation beaucoup plus facilement: Parsec est une monade transformateur, donc vous pouvez le mettre sur le dessus de l' IO
, puis utiliser liftIO
, alors qu'attoparsec est conçu autour de différentiels de traitement, de sorte que vous pouvez découper votre entrée de journal et les aspects du traitement (même si la journalisation dans l'analyseur peut être plus difficile). Il y a d'autres choix que de bien, mais je ne sais pas assez de détails pour en faire une recommandation. La plupart du combinateur parseur basé sur les bibliothèques ont tendance à avoir assez de conception similaire, donc je m'attends à de portage de votre code serait simple.
Une dernière option, si vous vraiment voulez tenir à ce que vous avez, serait d'examiner la mise en œuvre de l'analyse de la bibliothèque que vous utilisez actuellement et rouler vos propres IO
-orienté version de celui-ci. Mais ce n'est probablement pas l'idéal.
Aussi, comme un additif, si vous ce que vous êtes vraiment après n'est en fait pas de journalisation, mais se contenter de les suivre l'exécution de votre programme dans le cadre de développement, vous pouvez trouver le débogueur intégré dans GHCi être plus utile, ou de la bonne vieille printf débogage via le Debug.Trace module.
Edit: Ok, on dirait que vous avez des raisons plausibles pour envisager de déployer votre propre variation. Ce que vous avez environ voulons ici, c'est un ParserT
monade transformateur. Voici la définition actuelle de l' Parser
:
newtype Parser a = Parser { unParser :: S -> Either String (a, S) }
Le type S
est l'analyseur de l'état. Notez que c'est à peu près codé en dur version de StateT S (Either String) a
:
newtype StateT s m a = StateT { runStateT :: s -> m (a,s) }
...où est - Either String
est considéré comme une erreur de la monade. L' ErrorT
monade transformateur fait la même chose:
newtype ErrorT e m a = ErrorT { runErrorT :: m (Either e a) }
Ainsi, lorsque le type de courant est équivalent à StateT S (ErrorT String Identity)
, ce que vous voulez serait StateT S (ErrorT String IO)
.
Elle ressemble à la plupart des fonctions du module ne sont pas déconner avec le fonctionnement interne de l' Parser
de l'errance, de sorte que vous devriez être en mesure de simplement remplacer les définitions de type, offre le type des instances de classe, écrire votre propre runParser
de la fonction, et être bon d'aller.