2012-04-10 29 views
5

的玩具例子,但仍然令人沮喪:哈斯克爾拋出一個解析錯誤在一個陌生的地方

numberMapper:: IO() 
numberMapper = do codes <- forM [1 .. 4] (\num -> 
        do putStrLn $ "Enter a code for " ++ show num 
         code <- getLine 
         return code) 
        let numberCodes = zip [1 .. 4] codes 
        in forM numberCodes (\(num,code) -> 
        putStrLn $ "Got code " ++ show code ++ " for " ++ show num) 

ghci告訴我,我有一個Parse error in pattern: putStrLn,我想不通爲什麼它應該無法解析。

+1

好的,如果我在每個'語句'末尾添加括號來表示do塊和分號,那麼這個方法是有效的,但這是推薦的解決方案嗎? (它看起來有點不起作用:P) – agam 2012-04-10 08:13:29

+0

你可以假裝分號和大括號已經存在,但是看不見。 (有自動括號和分號去的地方的規則。) – 2012-04-10 08:23:38

回答

10

糾錯:

numberMapper:: IO() 
numberMapper = do 
    codes <- forM [1 .. 4] $ \num -> do 
     putStrLn $ "Enter a code for " ++ show num 
     getLine 
    let numberCodes = zip [1 .. 4] codes 
    forM_ numberCodes $ \(num,code) -> 
     putStrLn $ "Got code " ++ show code ++ " for " ++ show num 

修復:do塊中的行應排隊。

-- wrong 
a = do codes <- something 
     let numberCodes = zip [1..4] codes 

-- right 
a = do codes <- something 
     let numberCodes = zip [1..4] codes 

修復2:當使用let一個do塊內,不使用in

-- wrong 
func = do 
    let x = 17 
    in print x 

-- right 
func = do 
    let x = 17 
    print x 

修復3:使用forM_(返回(),又名無效),而不是forM(返回一個列表)。

codes <- forM [1..4] func... -- returns a list 
forM_ numberCodes $ ...  -- discards list, returns() 

所以forM_可能(幾乎是)這樣寫:

forM_ xs f = do forM xs f 
       return() 

小變化:你不需要return這裏:

do func1 
    x <- func2 
    return x 

你可以把它改成相當於,

do func1 
    func2 -- value of func2 is returned 
+0

哇...謝謝!! – agam 2012-04-10 20:58:27

4

您在您的do-blocks中過度縮進行。此外,do -blocks中的let語句不需要in

這個工作對我來說:

numberMapper:: IO() 
numberMapper = do codes <- forM [1 .. 4] (\num -> 
        do putStrLn $ "Enter a code for " ++ show num 
         code <- getLine 
         return code) 
        let numberCodes = zip [1 .. 4] codes 
        forM numberCodes (\(num,code) -> 
        putStrLn $ "Got code " ++ show code ++ " for " ++ show num) 

您也可以構建這樣的:

numberMapper:: IO() 
numberMapper = do codes <- forM [1 .. 4] $ \num -> 
        do putStrLn $ "Enter a code for " ++ show num 
         code <- getLine 
         return code 
        let numberCodes = zip [1 .. 4] codes 
        forM numberCodes $ \(num,code) -> 
        putStrLn $ "Got code " ++ show code ++ " for " ++ show num 

(它可以讓你避免括號;或者,把do\num ->結束並排列後續的陳述)