Une chose qui m'a toujours dérouté est de savoir s'il est temps ou non d'utiliser un IORef. Existe-t-il des directives à suivre pour décider d’utiliser ou non un IORef pour une tâche? Quel est le bon moment pour utiliser la monade d'État sur un IORef?
Réponses
Trop de publicités?De l'état et de sa relative ST à la fois produire des "monolithique" stateful des calculs qui peuvent être exécuter en tant qu'unités. Ils se sont contentés de traiter les mutable état que de données intermédiaire, qui est nécessaire pour produire un résultat, mais ne devrait pas, en soi, être d'intérêt pour le reste du programme.
D'autre part, ce que l'on met à l'intérieur d'un IORef n'est pas un "calcul" pour être exécuté -- c'est juste une case contenant une valeur simple qui peut être utilisé dans les IO en assez arbitraire façons. Cette zone peut être mis à l'intérieur de structures de données, passé autour de la (OI partie) le programme, ont son contenu remplacé chaque fois que sa pratique, être fermée par une fonction, etc. En fait, beaucoup de désordre de la nature des variables et pointeurs de langages tels que le C peut être modélisé avec IORefs, offrant une grande aide pour tout expert programmeur C désireux de faire respecter son / sa réputation d'être capable d'écrire du code C dans quelque langue que ce soit... C'est quelque chose de vraiment à être utilisé avec précaution.
Pourtant, il est parfois extrêmement difficile, voire impossible, d'isoler toutes les interactions avec un morceau de mutable état dans un seul bloc de code, certains morceaux de l'etat doit tout simplement être passé autour, de mettre à l'intérieur des structures de données etc. Dans de tels cas, la boîte peut être la seule option. Le chapitre présentant mutable état de l'Écrire Vous-même un Régime de 48 Heures tutoriel (très recommandé, par la voie) fournit un exemple. (Voir le lien pour une belle discussion de pourquoi il est plus approprié d'utiliser IORefs, par opposition à l'État ou à SAINT, pour le modèle de Régime environnements dans une certaine conception d'un interpréteur Scheme.)
En bref, ces environnements doivent être imbriqués de manière arbitraire, maintenu entre les instances de l'interaction de l'utilisateur (un (define x 1)
tapé au Régime REPL devrait vraisemblablement entraîner l'utilisateur de la possibilité plus tard de type en x
et obtenir 1 comme valeur), de mettre à l'intérieur des objets de modélisation Régime de fonctions (depuis le Régime de fonctions se refermer sur les environnements, ils sont créés dans) etc.
Pour résumer, je dirais que si une tâche semble bien adapté pour cela, l'État aura tendance à fournir la solution la plus propre. Si plusieurs pièces séparées de l'état sont nécessaires, peut-être ST peut vous aider. Si, toutefois, la dynamique de calcul est difficile à manier, voire impossible à enfermer dans son propre morceau de code, l'état a besoin de persister dans un formulaire modifiable pour une grande partie de la vie d'un programme complexe, etc., puis IORefs peut être juste la chose appropriée.
Et puis, si on doit le genre de mutable état, qui peut être passé autour et l'interaction avec contrôlée par IO code, pourquoi ne pas consulter STM et ses TVars! Ils sont beaucoup plus agréables dans la présence de la simultanéité, tellement, en fait, que de faire de la résolution de certains simultanéité des tâches liées à la réalité simple. Ce n'est pas vraiment liée à la question de savoir, si, si je vais résister à l'envie de l'expliquer. :-)
Hmm. Vous utiliseriez un IORef lorsque vous avez besoin d'un état mutable mais que vous vous trouvez dans un seul environnement threadé. Ou si vous voulez un champ modifiable à l'intérieur d'une structure plus grande qui est à son tour détenue par une variable de synchronisation.
En général, utilisez MVars. Ils ont une sémantique plus robuste.
Personnellement, je dirais que c'est bien d'utiliser IORef
s quand , et seulement quand vous utilisez déjà IO
. Sinon, toujours State
, sauf si vous avez besoin de la performance supérieure de la ST
. Il est possible d'utiliser plusieurs threads de l'etat avec la State
monade, avec quelques fonctions d'assistance – vous venez de faire l'état d'un n-uplet ou d'enregistrer, et de définir les fonctions à définir, obtenir ou mettre à jour chaque domaine séparément.
En particulier, il n'y a généralement pas beaucoup de point en utilisant StateT s IO
. Si vous êtes déjà en IO
, vous avez déjà mutable état, de sorte que vous pourriez aussi bien l'utiliser – ReaderT (IORef s) IO
par exemple.