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,但我不知道为什么它应该无法解析。

4

2 回答 2

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_(返回(),又名 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
于 2012-04-10T08:19:01.650 回答
4

你在你的 do-blocks 中过度缩进了行。此外,您不需要-block中的inforlet语句。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

(这可以让您避免使用括号;或者,将 thedo放在 the 的末尾\num ->并排列后续语句)

于 2012-04-10T08:18:18.713 回答