2010-05-31 67 views
7

壓痕哈斯克爾奇怪的錯誤,我有以下代碼:約的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 

我得到上面的註釋的行的錯誤,錯誤的是:

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

我正在使用emacs,沒有空格,我不明白我做錯了什麼。

回答

11

這在關於Haskell縮進的Wikibooks article的「if -within-do」部分中有解釋。

的問題是,在do -desugarer中,thenelse線條看起來像新的一樣的語句:

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

縮進thenelse線就能解決問題。

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糖,並使用模式匹配而不是headtailif-then-else控制結構。非正式地,這裏的>>=表示「將bar...的輸出從其IO包裝中取出並通過checkZero運行,返回結果」。