52 votes

En quel sens le Monad IO est-il pur?

J'ai eu le IO monade m'a décrit comme un État de monade où l'état est "le monde réel". Les partisans de cette approche IO prétendent que cela rend les opérations d'e / s pure, comme dans referentially transparent. Pourquoi est-ce? De mon point de vue, il apparaît que le code à l'intérieur de l'IO monade ont beaucoup d'observables effets secondaires. Aussi, n'est-il pas possible de décrire à peu près tout non-pure fonction comme une fonction de la réalité du monde? Par exemple, ne peut-on pas penser, dire, C malloc comme étant une fonction qui prend un Réaliste et un entier et renvoie un pointeur et un RealWorld, seulement, tout comme dans les IO monade le RealWorld est implicite?

Note: je sais ce qu'est une monade est et comment il est utilisé. Merci de ne pas répondre avec un lien au hasard de l'errance de tutoriel à moins que spécifiquement adresses à ma question.

60voto

mokus Points 2365

Je pense que la meilleure explication que j'ai entendu était en fait assez récemment, DONC. IO Foo est une recette pour la création d'un Foo. Une autre, plus littérale, manière de dire c'est que c'est un "programme qui produit un Foo. Il peut être exécuté (plusieurs fois) pour créer un Foo ou mourir en essayant. L'exécution de la recette/programme est ce que nous voulons finalement (sinon, pourquoi en écrire un?), mais la chose qui est représenté par un IO action dans notre code est la recette elle-même.

Cette recette est une pure valeur, exactement dans le même sens que l' String est une pure valeur. Les recettes peuvent être combinés et manipulés dans intéressants, parfois étonnante, des moyens, mais les nombreuses façons dont ces recettes peuvent être combinés (à l'exception du flagrante non-pure, unsafePerformIO, unsafeCoerce, etc.) sont tous complètement referentially transparent, déterministe, et tous les trucs sympa. L'résultant de la recette dépend en aucune manière que ce soit sur l'état de rien d'autre que les recettes qu'il a été construit à partir de.

16voto

Dario Points 26259

Aussi, n'est-il pas possible de décrire à peu près tout non-pure fonction comme une fonction de la réalité du monde? Par exemple, ne peut-on pas penser, dire, C malloc comme étant une fonction qui prend un Réaliste et un entier et renvoie un pointeur et un RealWorld, seulement, tout comme dans les IO monade le RealWorld est implicite?

Pour sûr ...

L'idée de la programmation fonctionnelle est de décrire les programmes comme une combinaison de petites, les indépendants, les calculs de la construction de plus gros calculs.

Ces indépendante des calculs, vous aurez de nombreux avantages, allant de concise programmes de manière efficace et efficiente parallélisables codes, la paresse jusqu'à l'rigoureux de garantir que le contrôle de flux comme prévu - avec aucune chance de l'interférence ou la corruption de données arbitraires.

Maintenant - dans certains cas (comme IO), nous avons besoin d'impur code. Les calculs impliquant de telles opérations ne peuvent pas être indépendants, ils peuvent muter de données arbitraires d'un autre calcul.

Le point est - Haskell est toujours pure, IO ne change pas cela.

Donc, notre impur, non indépendants et des codes pour obtenir une commune de la dépendance que nous avons à passer une RealWorld. Donc quel que soit le spi calcul nous voulons, nous devons passer par cette RealWorld chose pour appliquer les changements et toutes les autres stateful calcul veut voir ou de faire des modifications, à savoir l' RealWorld trop.

Que ce soit explicitement ou implicitement, par le biais de l' IO monade n'est pas pertinent. Vous construisez un Haskell programm comme un géant de calcul qui transforme les données, et une partie de ces données est l' RealWorld.

Une fois la première main :: IO () qui est appelé lorsque votre programme est exécuté avec les cours actuels du monde réel comme un paramètre, ce monde réel obtient sur l'ensemble impur calculs impliqués, comme données en State. C'est ce que monadique >>= prend soin de.

Et où l' RealWorld n'obtiennent pas (comme dans le plus pur calculs ou sans >>=-ing main), il n'y a aucune chance de faire quelque chose avec elle. Et où est - t get, qui est passé par purement fonctionnelle en passant de (implicite) de paramètre. C'est pourquoi

let foo = putStrLn "AAARGH" in 42

ce qui n'a absolument rien - et pourquoi l' IO monade - comme tout le reste - est de la pure. Ce qui se passe à l'intérieur de ce code peut bien sûr être impur, mais il est tout coincé à l'intérieur, n'a aucune chance d'interférer avec les non-connectés calculs.

10voto

yairchu Points 9694

Supposons que nous avons quelque chose comme:

animatePowBoomWhenHearNoiseInMicrophone :: TimeDiff -> Sample -> IO ()
animatePowBoomWhenHearNoiseInMicrophone
    levelWeightedAverageHalfLife levelThreshord = ...

programA :: IO ()
programA = animatePowBoomWhenHearNoiseInMicrophone 3 10000

programB :: IO ()
programB = animatePowBoomWhenHearNoiseInMicrophone 3 10000

Voici un point de vue:

animatePowBoomWhenHearNoiseInMicrophone est une fonction pure, dans le sens que ses résultats pour une même entrée, programA et programB, sont exactement les mêmes. Vous pouvez le faire main = programA ou main = programB et ce serait exactement la même.

animatePowBoomWhenHearNoiseInMicrophone est une fonction reçoit deux arguments et résultant en une description d'un programme. Le Haskell d'exécution peuvent exécuter cette description si vous définissez main , ou autrement l'inclure dans main via la liaison.

Qu'est - IO? IO est un DSL pour la description des programmes impératifs, codé en "pure-haskell" structures de données et des fonctions.

"complète-haskell" aka GHC est une mise en œuvre à la fois de "pure-haskell", et un impératif de mise en œuvre de l' IO /décodeur exécuteur.

8voto

Tim Matthews Points 2975

Tout simplement en revient à l'égalité extensionnelle:

Si vous vous appelez getLine deux fois, puis deux appels renvoyer un IO String qui serait exactement le même aspect à l'extérieur à chaque fois. Si vous deviez écrire une fonction pour faire des 2 IO Strings et de retourner l' Bool de signal détecté de différence entre les deux, il ne serait pas possible de détecter une différence de toutes les propriétés observables. Il ne pouvait pas demander à toute autre fonction qu'ils sont égaux et toute tentative à l'aide d' >>= doit aussi rendre quelque chose en IO qui sont tous equall de l'extérieur.

3voto

Ozgur Points 668

Même si son titre est un peu étrange (en ce sens qu'il ne correspond pas exactement au contenu), le fil de discussion haskell-cafe suivant contient une bonne discussion sur les différents modèles d'E / S pour Haskell.

http://www.mail-archive.com/haskell-cafe@haskell.org/msg79613.html

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X