7
votes

Évaluation paresseuse et confusion d'effet secondaire io

Ce code (extrait de Décentrez-vous un haskell ): XXX PRE>

Apparemment Desgesnes à p>

putStrLn "What is your name?" >>= 
   (\_ ->
      getLine >>=
         (\name ->
            putStrLn ("Nice to meet you, " ++ name ++ "!")))


1 commentaires

"Les Lambdas ignorent leurs arguments, lors de l'évaluation paresseuse, ce type de chose n'est censé être reconnu et court-circuité?" Tu paries! Le deuxième argument à (>> =) est une fonction particulièrement paresseuse ici, mais le (>> =) fonction elle-même n'est pas paresseux.


5 Réponses :


10
votes

Lire le " S'attaquer à l'équipe gênante "Papier par Simon Peyton Jones.

Pour des questions connexes, voir P>


3 commentaires

Il est intéressant de noter que tout le monde explique toujours >> = sur les valeurs IO par analogie. N'a-t-il pas une définition quelque part dans le prélude? Pourquoi personne ne le cite-t-il jamais? Est lié sur io où la magie se produit? Je lis le papier d'équipe maladroite en ce moment et même SPJ vous échappe de définir réellement la liaison


Le type io est abstrait, il n'y a donc personne de définition de >> = dans la norme HASKELLL. Selon la manière dont vous implémentez io , vous aurez des implémentations différentes de >> = . Si vous approchez dans GHC, vous constaterez que io est une monade d'état et >> = est simplement lié pour une monade d'état. (Il y a plus de magie à l'intérieur du compilateur pour rendre cela efficace.)


@Thelronknuckle Ce n'est pas une analogie sur les "valeurs". C'est une analogie sur une autre implémentation d'IO pure à l'aide de l'ancien Main :: [Demande] -> [réponse] idée. La partie la plus intéressante n'est également pas liée, mais du runio pour io monade. Comme Io Monad est abstrait, nous devons soit fournir une explication abstraite en tant que SPJ, ou utilisez une stratégie de mise en œuvre comme moi.



1
votes

Je pense que cela est plus compréhensible si vous pensez à nouveau aux actions en tant que fonctions. Votre exemple de liaison ( do {foo <- getline; poststrln foo;} ) est de manière intuitive similaire à la fonction suivante: xxx

sauf que la fonction est une transaction. Notre appel FUNC (ARG) est évalué, le cas échéant si (arg) est terminé avec succès. Sinon, nous échouons dans notre action.

Ceci est différent des fonctions ordinaires, car alors Haskell ne se soucie vraiment pas si (arg) calcule complètement ou à Tout, jusqu'à ce que le point ait besoin d'un peu de Func (arg) pour poursuivre le programme.


0 commentaires

9
votes

regarder io code> dans une réelle implémentation de haskell confondra probablement plus qu'elles éclaire. Mais pensez que io code> comme étant défini comme celui-ci (cela suppose que vous connaissez des gains): xxx pré>

donc lorsque vous évaluez un programme (de type io () code>) Tout ce qu'il fait est de créer une structure de données de type io () code> qui décrit comment l'interaction avec le monde se produira une fois que vous l'exécutez. Vous pouvez alors imaginer que le moteur d'exécution étant écrit, par exemple, C, et il y a là où tous les effets se produisent. P>

SO P>

main = Bind (PutStr "Hey, ") (\ _ -> Bind (PutStr "I'm ") (\ _ -> PutStr "Andy!"))


1 commentaires

+1 pour l'approche de GADT et le «regard sur l'IO dans une réelle implémentation de Haskell confondra probablement plus qu'elles éclaire».



3
votes

Je pense avoir juste besoin de voir la définition de la liaison pour io, puis sera tout clair.

Oui, vous devriez le faire. C'est en fait assez facile, et si je me remette correctement, ça va comme xxx

le "truc" est que chaque valeur IO est en fait fondamentalement une fonction, mais pour l'évaluer, vous auriez besoin de Un jeton de type realworld . Il n'y a qu'une seule instance qui peut fournir une telle valeur - le système d'exécution fonctionnant principal (et, bien sûr, la fonction qui ne doit pas être nommée).


0 commentaires

1
votes

Je pense que je dois juste voir la définition de bind code> IO code> et alors il sera clair. P>

  IO (\ s0 -> let !(# s1, _ #)    = unIO (putStrLn "What is your name?") s0 in
              let !(# s2, name #) = unIO getLine s1 in
              let !(# s3, a3 #)   = unIO (putStrLn ("Nice to meet you, " ++ name ++ "!")) s2 in
              (# s3, a3 #))


0 commentaires