2010-07-11 4 views
4

Voici un exemple de programme du livre RWH. Je me demande pourquoi le premier fonctionne bien mais le second ne peut même pas compiler? La seule différence est que le premier utilise 2 onglets après where mainWith func = do alors que le second utilise seulement 1. Ne sais pas quelle différence cela signifie-t-il? Pourquoi la seconde ne parvient pas à compiler? Et aussi pourquoi do construct peut être vide?Quel rôle joue l'indentation ici? et pourquoi un tiret ne fonctionne pas?

Merci beaucoup, Alex

-- Real World Haskell Sample Code Chapter 4: 
-- http://book.realworldhaskell.org/read/functional-programming.html 

import System.Environment (getArgs) 

interactWith func input output = do 
    s <- readFile input 
    writeFile output (func s) 

main = mainWith myFunction 
    where mainWith func = do 
      args <- getArgs 
      case args of 
       [fin, fout] -> do 
        interactWith func fin fout 
       _ -> putStrLn "error: exactly two arguments needed" 

myFunction = id 


-- The following code has a compilation error 
-- % ghc --make interactWith.hs 
-- [1 of 1] Compiling Main    (interactWith.hs, interactWith.o) 
-- 
-- interactWith.hs:8:26: Empty 'do' construct 


import System.Environment (getArgs) 

interactWith func input output = do 
    s <- readFile input 
    writeFile output (func s) 

main = mainWith myFunction 
    where mainWith func = do 
     args <- getArgs 
     case args of 
      [fin, fout] -> do 
       interactWith func fin fout 
      _ -> putStrLn "error: exactly two arguments needed" 

myFunction = id 

Répondre

7

La définition de la fonction mainWith est en retrait à la colonne 10:

where mainWith func = do 
     ^

Le contenu du bloc do commencé dans cette ligne ne sont en retrait à la colonne 8:

 args <- getArgs 
     case args of 
      ... 
     ^

Si vous augmentez l'indentation du contenu du bloc do devant également être indentée au moins jusqu'à la colonne 10, le code est analysé correctement. Avec l'indentation actuelle, les lignes qui devraient appartenir au bloc do sont considérées comme faisant partie de la clause where, mais pas la fonction mainWith.

+0

ah, wow, c'est mystérieux. Merci beaucoup, ça explique. Je ne m'attendais pas à ce que le retrait commence après "où". –

+0

@Alex: C'est parce que 'where' a son propre niveau d'indentation (commençant comme prévu au' w'). Vous pouvez définir plusieurs fonctions dans un seul bloc 'where'. La définition de fonction self démarre son propre niveau d'indentation, distinct de celui introduit par 'where'. – sth

0

Le do -bloc ne peut être vide, c'est la raison pour laquelle vous obtenez l'erreur. Lorsque vous utilisez un seul onglet args <- getArgs est considéré comme faisant partie du bloc where, pas le bloc do, donc le bloc est vide et vous obtenez une erreur. Le fait est que, sauf si vous utilisez {} et ; pour indiquer explicitement quel bloc va où d'où, haskell repose sur indendation. Et puisque vous indentiez votre ligne d'un seul niveau, il était considéré comme faisant partie du bloc where.

Questions connexes