2010-05-31 16 views
7

Mam następujący kod:dziwny błąd w Haskell o wcięcia 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 

pojawia się błąd na linii z komentarzem powyżej, błąd jest:

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

Pracuję z emacs, nie ma spacji i nie rozumiem, co zrobiłem źle.

Odpowiedz

11

Zostało to wyjaśnione w sekcji "if" wna wcięciu Haskella.

Problemem jest to, że do do -desugarer, że then i else linie wyglądają jak nowe informacje:

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

Wcięcia te then i else linie rozwiąże ten problem.

UPDATE: Ponieważ jest to oznaczone beginner, ja również zauważyć, że coś jak poniżej będzie na ogół uważane za bardziej idiomatycznych w 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 

To robi dokładnie to samo, co Twoja foo, ale unika się cukru i wykorzystuje dopasowywanie do wzorca zamiast head i tail i strukturę kontrolną. Nieformalnie, tutaj >>= mówi "wyjmij z urządzenia bar... wyjście i otrzyj je przez checkZero, zwracając wynik".