2010-05-31 68 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运行,返回结果”。