2017-02-13 4 views
0

Je veux écrire une boucle en haskell en utilisant des monades mais j'ai du mal à comprendre le concept.Exemple de boucle while dans Haskell utilisant monads

Quelqu'un pourrait-il me fournir un exemple simple d'une boucle while alors que certaines conditions sont satisfaites impliquant une action IO? Je ne veux pas d'un exemple abstrait mais d'un réel concret qui fonctionne.

+0

Est-ce que [cette question] (http://stackoverflow.com/questions/17719620/while-loop-in-haskell-with-a-condition) aide? – Mephy

+1

duplication possible de [Alors que la boucle dans Haskell avec une condition] (http://stackoverflow.com/questions/17719620/while-loop-in-haskell-with-a-condition) – jberryman

+0

Je l'ai déjà vu, mais y en at-il un même plus simple où je peux facilement dire ce que le programme essaie de calculer immédiatement. – domoremath

Répondre

4

Ci-dessous, il y a un exemple horrible. Tu étais prévenu.

Tenir compte du pseudo-code:

var x = 23 
while (x != 0) { 
    print "x not yet 0, enter an adjustment" 
    x = x + read() 
} 
print "x reached 0! Exiting" 

Voici sa traduction pièce par pièce en Haskell, en utilisant un style impératif, autant que possible.

import Data.IORef 

main :: IO() 
main = do 
    x <- newIORef (23 :: Int) 
    let loop = do 
      v <- readIORef x 
      if v == 0 
      then return() 
      else do 
      putStrLn "x not yet 0, enter an adjustment" 
      a <- readLn 
      writeIORef x (v+a) 
      loop 
    loop 
    putStrLn "x reached 0! Exiting" 

Ce qui précède est en effet horrible Haskell. Il simule la boucle while en utilisant le loop récursif-défini, qui n'est pas trop mauvais. Mais il utilise IO partout, y compris pour imiter les variables mutables de style impératif.

Une meilleure approche pourrait être d'éliminer ceux IORef s.

main = do 
    let loop 0 = return() 
     loop v = do 
      putStrLn "x not yet 0, enter an adjustment" 
      a <- readLn 
      loop (v+a) 
    loop 23 
    putStrLn "x reached 0! Exiting" 

Pas élégant code par aucun étirement, mais au moins le "garde" ne fait pas inutile IO.

Habituellement, les programmeurs Haskell s'efforcent de séparer autant que possible le calcul pur de l'E/S. C'est parce que cela conduit souvent à un code meilleur, plus simple et moins sujet aux erreurs.