Question

Une chose qui m'a toujours confus est de savoir si oui ou non il est un temps acceptable d'utiliser un IORef. Y a-t-il des directives qui doivent être suivies au moment de décider si oui ou non d'utiliser un IORef pour une tâche? Quand un bon moment pour utiliser la monade de l'Etat sur un IORef?

Était-ce utile?

La solution

Etat et son rapport ST à la fois produire les calculs avec état `monolithiques » qui peuvent être exécutées sous forme d'unités. Ils traitent essentiellement l'état mutable sous forme de données intermédiaires, ce qui est nécessaire pour produire un résultat, mais ne devrait pas, en soi, 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 » à exécuter - il est juste une boîte contenant une valeur simple qui peut être utilisé dans les IO de façon assez arbitraire. Cette boîte peut être mis à l'intérieur des structures de données, passé autour de la (partie IO) du programme, ont son contenu remplacé chaque fois que sa pratique, être fermée par un fonction, etc. En fait, beaucoup de la nature désordonnée des variables et pointeurs de langages comme C peuvent être modélisés avec IORefs, fournissant une aide précieuse à tout programmeur C expert qui souhaite maintenir sa / sa réputation d'être en mesure d'écrire du code C dans la langue ... C'est quelque chose certainement être utilisé avec soin.

Pourtant, il est parfois très difficile à manier, sinon carrément impossible, d'isoler toutes les interactions avec un morceau de l'état mutable dans un bloc de code unique - des pièces d'Etat doivent simplement être transmis autour, mis à l'intérieur des structures de données, etc. Dans ce cas, l'approche de la boîte peut être la seule option. Le chapitre du écrire vous-même un schéma dans 48 heures tutoriel (fortement recommandé, par la voie) fournit un exemple. (Voir le lien pour une belle discussion des raisons pour lesquelles il est vraiment le plus approprié d'utiliser IORefs, par opposition à l'État ou ST, pour modéliser des environnements Scheme dans une certaine conception d'un interpréteur Scheme).

En bref, ces environnements doivent être imbriqués de façon arbitraire, maintenu entre les instances d'interaction utilisateur (un (define x 1) tapé au schéma REPL devrait vraisemblablement donner lieu à l'utilisateur d'être plus tard capable de taper x et revenir 1 la valeur ), mettre des objets dans la modélisation des fonctions Scheme (puisque les fonctions Scheme proches sur les environnements dans lesquels ils sont créés) etc.

Pour résumer, je dirais que si une tâche semble tout bien adapté pour elle, l'État aura tendance à fournir la solution la plus propre. Si plusieurs pièces séparées de l'Etat sont nécessaires, peut-être ST peut vous aider. Toutefois, si le calcul stateful est trop compliqué ou impossible d'enfermer dans son propre morceau de code, l'état doit persister sous une forme modifiable pour une grande partie de la vie d'un programme complexe, etc., alors IORefs peut être juste la chose appropriée.

Là encore, si l'on a besoin de la sorte d'état mutable qui peut être passé autour et interagi avec de manière contrôlée par le code IO, pourquoi ne pas consulter STM et ses TVars! Ils sont beaucoup plus agréable en présence de la concomitance, tant et si bien, en fait, de faire résoudre des tâches liées à fait simple-accès concurrentiel. Ce n'est pas vraiment liée à la question, bien que, donc je vais résister à exhorter à élaborer. : -)

Autres conseils

Hmm. Vous souhaitez utiliser un IORef quand vous avez besoin un état mutable, mais sont dans un seul environnement fileté. Ou si vous voulez un champ mutable dans une structure plus large qui est à son tour détenue par une variable de synchronisation.

En général, utilisez MVAR. Ils ont une sémantique plus robustes.

Personnellement, je dirais que c'est bon d'utiliser IORefs lorsque et seulement quand vous utilisez déjà IO. Dans le cas contraire, State toujours, à moins que vous avez besoin des performances supérieures de ST. Il est possible d'utiliser plusieurs threads d'état avec la monade State, avec quelques fonctions d'aide -. Vous venez de faire l'état un tuple ou un enregistrement, et définir des fonctions pour définir, d'obtenir ou de mettre à jour chaque champ séparément

En particulier, il n'y a généralement pas beaucoup d'intérêt à l'aide StateT s IO. Si vous êtes déjà en IO, vous avez déjà état mutable, vous pourriez aussi bien l'utiliser - ReaderT (IORef s) IO par exemple

.

J'utilise STRef lorsque l'état est localisé et ne nécessitent pas d'interaction avec l'environnement.

scroll top