Haskell在一个陌生的地方抛出一个解析错误

时间:2012-04-10 08:09:14

标签: haskell parse-error

一个玩具示例,但仍然令人沮丧:

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,我无法弄清楚为什么它无法解析。

2 个答案:

答案 0 :(得分: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_(返回(),a.k.a。void)而不是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

答案 1 :(得分:4)

你在do-blocks中过度缩进行。此外,in - let中的do语句不需要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 ->放在{{1}}的末尾并排列后续语句