2010-05-31 14 views
7

Ho il seguente codice:strano errore di Haskell circa rientro del if-then-else

foo :: Int -> [String] -> [(FilePath, Integer)] -> IO Int 
foo _ [] _ = return 4 
foo _ _ [] = return 5 
foo n nameREs pretendentFilesWithSizes = do 
    result <- (bar n (head nameREs) pretendentFilesWithSizes) 
    if result == 0 
    then return 0 -- <========================================== here is the error 
    else foo n (tail nameREs) pretendentFilesWithSizes 

ottengo un errore sulla linea con il commento di cui sopra, l'errore è:

aaa.hs:56:2: 
    parse error (possibly incorrect indentation) 

Sto lavorando con emacs, non ci sono spazi e non capisco cosa ho fatto di sbagliato.

risposta

11

Questo è spiegato nella sezione "if -con-do" di Wikibooks article sul rientro di Haskell.

Il problema è che al do -desugarer, i then e else linee sembrano nuove:

do { first thing 
    ; if condition 
    ; then foo 
    ; else bar 
    ; third thing } 

Rientro le linee then e else risolverà il problema.

UPDATE: poiché questo è tagged beginner, sarò anche notare che qualcosa di simile al seguente sarebbe generalmente essere considerato più idiomatica in Haskell:

foo :: Int -> [String] -> [(FilePath, Integer)] -> IO Int 
foo _ [] _ = return 4 
foo _ _ [] = return 5 
foo n (r:rs) filesWithSizes = bar n r filesWithSizes >>= checkZero 
    where 
    checkZero :: Int -> IO Int 
    checkZero 0 = return 0 
    checkZero _ = foo n rs filesWithSizes 

Questo fa esattamente la stessa cosa come il vostro foo, ma evita lo zucchero do e utilizza la corrispondenza del modello anziché head e tail e la struttura di controllo if-then-else. Informalmente, lo >>= qui dice "prendi l'uscita di bar... dal suo wrapper IO ed eseguila attraverso checkZero, restituendo il risultato".

Problemi correlati