La IO
monade à Haskell est souvent décrite comme une monade d’État où l’État est le monde. Ainsi, une valeur de type IO a
monad est considérée comme quelque chose comme worldState -> (a, worldState)
.
Il y a quelque temps, j'ai lu un article (ou un article de blog / liste de diffusion) qui critiquait ce point de vue et donnait plusieurs raisons pour expliquer que ce n'était pas correct. Mais je ne me souviens ni de l'article ni des raisons. Quelqu'un sait?
Edit: L'article semble perdu, commençons donc à rassembler divers arguments ici. Je commence une prime pour rendre les choses plus intéressantes.
Edit: L’article que je cherchais s’attaque au groupe délicat: entrées / sorties monadiques, accès simultanés, exceptions et appels en langue étrangère dans Haskell de Simon Peyton Jones. (Merci à la réponse de TacTics.)
la source
Réponses:
Le problème
IO a = worldState -> (a, worldState)
est que si cela était vrai, nous pourrions le prouverforever (putStrLn "Hello") :: IO a
et nousundefined :: IO a
sommes égaux. Voici la preuve fournie par dolio (2010, irc):Lemme:
(\r w -> r (snd $ m w)) ⊥ = ⊥
Donc
forever m = fix (\r -> \w -> r (snd $ m w)) = ⊥
En particulier
forever (putStrLn "Hello") = ⊥
et par conséquentforever (putStrLn "Hello")
,undefined
sont des programmes équivalents. Cependant, il est clair qu'ils ne sont pas censés être considérés comme des programmes équivalents, en théorie ou en pratique.Notez que ce modèle est faux même sans invoquer la simultanéité.
la source
undefined
la sémantique pure de Haskell? Différents s sont supposés être indiscernables dans la sémantique pure de Haskell! Mais lorsque nous réfléchissons de manière opérationnelle à nos programmes, nous voulons également distinguer différents types de, même lorsque celaIO
n’est pas impliqué; Je me soucie de savoir si mon programme génère une exception ou entre dans une boucle infinie, même si vous pouvez prouver que ces éléments sont égaux en prouvant qu'ils sont tous les deux. Ce n'est pas réellement une contradiction cependant.forever (putStrLn "Hello")
n'est pas comme[0,1..]
, sûrement. Votre preuve n'est pas particulière àworldState
, donc elle s'applique également à la monade d'état régulière. Doncforever (someModificationWith "Hello")
est aussi dénotationnellement équivalent à ⊥. Je ne suis absolument pas surpris par ce résultat. cela n'est pas productif dans la sémantique dénotationnelle, et ce que l'ordinateur fait de manière opérationnelle pendant que nous attendons éternellement est sans importance. Même chose pourforever (putStrLn "Hello")
; cela ne produit pas et ne devrait pas produire un nouvel état mondial que nous pouvons consommer paresseusement.Voici une réponse triviale: tout changement d'état de la monade est dû à des actions effectuées dans la monade. Si en effet l'explication «WorldState -> (a, WorldState)» revendique la même propriété, WorldState étant une valeur pure que seule la monade IO change, c'est faux. Les changements d’heure, le contenu des fichiers, l’état des descripteurs, etc. peuvent changer indépendamment de ce qui se passe dans la monade IO. C'est le but de la monade IO. Le fait que GHC transmette une valeur RealWorld (ou sa valeur inférieure) en dessous est une garantie de la régularité des choses, pour autant que je sache, si cela peut (être juste quelque chose à mettre dans la valeur ST).
la source
J'ai écrit un article de blog sur le sujet de la modélisation de l'IO en tant que forme de coroutine asymétrique communiquant avec le système d'exécution de votre langue. (Il est vrai que c'est la troisième partie d'une série)
http://comonad.com/reader/2011/free-monads-for-less-3/
Cet article explique en partie pourquoi il est délicat de raisonner sur la sémantique du "dépassement du monde".
la source
Voir S'attaquer à l'escouade maladroite .
La grande raison en est que les modèles d'état RealWorld de la monade d'IO ne fonctionnent pas bien avec la simultanéité. SPJ dans ce classique lisible privilégie l’utilisation d’une sémantique opérationnelle pour la comprendre.
la source
La principale plainte des modèles d’état de RealWorld est que, comme le dit TacTics, le passage d’un monde à l’autre ne fonctionne pas nécessairement avec la simultanéité. Mais Wouter Swierstra et Thorsten Altenkirch ont montré comment raisonner la concurrence comme un effet de "passage du monde", avec une séquence fixe mais arbitraire de fils entrelacés dans leur article "La beauté de la bête: une sématique fonctionnelle pour le groupe fantaisiste": http : //www.staff.science.uu.nl/~swier004/Publications/BeautyInTheBeast.pdf
Le code correspondant à cela est sur Hackage comme IOSpec: http://hackage.haskell.org/package/IOSpec
Je pense que la thèse de Wouter va plus en détail: http://www.staff.science.uu.nl/~swier004/Publications/Thesis.pdf
la source