8
votes

Coque Haskell élégant / manipulation des erreurs dans des monades séquentielles

parce que j'ai trop simplifié dans mon Autre question avant, je voudrais donner un Exemple plus clair ici.

Comment puis-je gérer des situations où je dois vérifier les conditions de certian de manière séquentielle sans imbrication de plusieurs cas? Avec "manière séquentielle", je veux dire avoir une valeur (par exemple de STDIN), vérifier cette valeur pour une certaine condition et en fonction du résultat obtenant une autre valeur, etc. p>

Exemple: P>

sequen :: IO String
sequen = do
  a <- getLine
  case a of
    "hi" -> do
      putStrLn "hello!"
      b <- getLine
      case b of
        "how are you?" -> do
          putStrLn "fine, thanks"
          return "nice conversation"
        _ -> return "error 2"
    _ -> return "error 1"


0 commentaires

5 Réponses :


0
votes

AVERTISSEMENT: Sonkell Newbie répondant à Haskell.

Vous pouvez éviter ce type d'escalier avec la monade peut-être. Bon exemple au début de Ce chapitre

Cependant, vous voudriez quelque chose de similaire avec une monadique soit (probablement il en existe un) car vous retournez des codes d'erreur.

L'idée de base étant qu'une fois que vous avez une erreur "gauche de 1", vous ferez un court-circuit toutes les étapes futures (en raison de l'évaluation paresseuse).


2 commentaires

Ah, je vois que j'étais sur la bonne voie selon @gabriel ci-dessous.


À cause de l'évaluation paresseuse? Ou en raison de la définition de l'instance monad pour ?



22
votes

Bien sûr. Ceci est précisément ce que eithert a été fait. Vous pouvez l'obtenir à partir de contrôler.monad.trans.e dans le package eithert . xxx

eithert Aborte le bloc de code actuel chaque fois qu'il rencontre une instruction gauche et les personnes utilisent généralement pour indiquer les conditions d'erreur.

Le type de bloc intérieur est eithert int io string . Lorsque vous RUNEITERTERTER IT, vous obtenez io (Soit String) . Le type gauche correspond au cas où il a échoué avec un gauche et la valeur droite signifie qu'il atteint avec succès la fin du bloc.


5 commentaires

Impressionnant. Exactement ce que je voulais savoir. Merci!


Sur la note d'Eithert, j'ai écrit un article de blog sur ce qui a été assez bien reçu: ocharles.org.uk/blog/posts/2012-07-24-in-prise-freithert.h tml


@ochars j'ai lu cela il y a un moment et j'ai pensé que cela devrait être la solution à mon problème, mais je ne pouvais pas l'appliquer jusqu'à présent. Vous pouvez créer un lien vers cette question dans votre message :)


@Gabriel avez-vous l'intention d'Eithert de remplacer complètement les cas d'utilisation errortronomique? J'utilise Errort depuis longtemps, mais je trouve parfois gênant de déclarer l'instance d'erreur pour toutes mes classes d'exception.


J'aimerais vraiment eithert pour remplacer errort pour tous les cas d'utilisation possibles. Le problème est que Edward KMett et que j'ai du mal à convaincre Ross Patterson à (a) supprimer la contrainte d'erreur d'erreur à partir de ERRORT ou (b) Ajouter ESHERTERT à transformateurs . C'est la tenue pour le moment.



2
votes

Puisque vous êtes nécessairement dans le io monad, vous ferez mieux d'utiliser les fonctionnalités de gestion des erreurs monad au lieu d'empiler une erreur monade sur io . Il évite tout le lift lourde ing: xxx

Dans ce cas, vos erreurs sont simplement String S, qui sont lancées par < Code> io 'S échoue , en tant que userError . Si vous souhaitez lancer un autre type, vous devrez utiliser lancer au lieu de échouer .


0 commentaires

5
votes

J'ai écrit une série de messages un moment de retour sur mes propres apprentissages du & eithert types. Vous pouvez le lire ici: http://watchrisearn.com/ Blog / 2013/12/01 / Travailler - entièrement-in-eithert /

J'utilise les erreurs Erreurs Pour obtenir un tas de beaux aides à l'aide d'Eithert ( à gauche et DROITE Fonctions, par exemple pour revenir aux versions soulevées de gauche et droit ).

En extrayant votre Les conditions de défaillance potentielles dans leurs propres assistants, vous pouvez rendre la liste principale de votre code lu totalement séquentiellement séquentiellement, sans aucune déclaration de cas de vérification des résultats.

à partir de ce poteau, vous pouvez voir comment le runeithert La section est une partie de travail séquentielle, il se trouve que la mécanique de défaillance de eithert . Évidemment, ce code est équité à montrer comment maybet joue à l'intérieur de eithert aussi. En vrai code, ce serait juste l'histoire que vous vouliez dire, avec un seul gauche / droit à la fin. xxx


1 commentaires

Vieux exemple! Merci d'avoir souligné que vous pouvez mettre les cas dans des fonctions distinctes. Rend la fonction principale beaucoup plus agréable à lire.



1
votes

à un moment donné Le package eithert a été obsolète (bien que Transformers - offre une API similaire). Heureusement, il y a une alternative à eithert qui ne nécessite même pas d'installer un package séparé.

L'installation standard Haskell est livrée avec le contrôle.monad.trans.except module (à partir du Transformers Package, qui est fourni avec GHC), ce qui se comporte presque de manière identique à eithert . Le code résultant est presque identique au code dans réponse de Gabriella Gonzalez , mais en utilisant runexcept à la place de runeithert et jets au lieu de laissé . xxx

(Notez que le plus susmentionné Transformers - est en fait une enveloppe pour sauf Conçu pour fournir une compatibilité avec le code qui utilise toujours eithert .)


0 commentaires