Haskell throws a parse error in a strange place

A toy example, but still frustrating:

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)

ghcitells me what I have Parse error in pattern: putStrLn, and I canโ€™t understand why he should not understand.

+5
source share
2 answers

Correction:

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

Correction: Lines inside the block doshould line up.

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

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

Fix 2: When using letinside a block, dodo not use in.

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

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

Fix 3: Use forM_(which returns (), aka void) instead of forM(which returns a list).

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

So, forM_you can (almost) write as follows:

forM_ xs f = do forM xs f
                return ()

: return :

do func1
   x <- func2
   return x

,

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

. , 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 -> )

+4

All Articles