2010-05-31 1 views
7

я следующий код:странная ошибка в Haskell о выемке, если-то-еще

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 

Я получаю ошибку на линии с комментарием выше, ошибка:

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

Я работаю с emacs, нет пробелов, и я не понимаю, что я делал неправильно.

ответ

11

Это объясняется в разделе «if -within- do» раздела Wikibooks article на отступе Haskell.

Проблема заключается в том, что в do -desugarer, в then и else линии выглядят как новые заявления:

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

отступов в then и else линии будет решить эту проблему.

UPDATE: Поскольку это помечено beginner, я также отметить, что-то вроде следующего, как правило, считается более идиоматических в 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 

Это делает то же самое, как ваш foo, но он избегает сахара и использует сопоставление образцов вместо head и tail и структуру управления if-then-else. Неформально здесь >>= говорит: «Сделайте вывод bar... из своей обертки IO и запустите его через checkZero, возвращая результат».

Смежные вопросы