У меня есть следующий код:
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, нет никаких пробелов, и я не понимаю то, что сделало я делаю неправильно.
Отступ then
и else
строк на один уровень больше. Однако все может измениться Conditionals и do
-notation.
Это объясняется в разделе "if
-within-do
" статьи Wikibooks об отступах в Haskell.
Проблема в том, что для do
-десуггеров строки 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
, но избегает сахара do
и использует согласование шаблонов вместо head
и tail
и структуры управления if-then-else
. Неформально, >>=
здесь означает "вывести вывод bar...
из его IO
обертки и пропустить его через checkZero
, вернув результат".