【问题标题】:Haskell throws a parse error in a strange placeHaskell 在一个奇怪的地方抛出一个解析错误
【发布时间】:2012-04-22 12:52:07
【问题描述】:

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

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

【问题讨论】:

  • 好的,如果我在每个“语句”的末尾为 do 块和分号添加大括号,这将有效——但这是推荐的解决方案吗? (它似乎有点不起作用:P)
  • 您可以假装分号和大括号已经存在,但不可见。 (自动大括号和分号的位置有规则。)

标签: haskell parse-error


【解决方案1】:

更正:

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:do 块内使用 let 时,不要使用 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

【讨论】:

    【解决方案2】:

    你在你的 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 -&gt; 的末尾并排列后续语句)

    【讨论】:

      猜你喜欢
      • 2021-11-18
      • 2015-05-23
      • 2016-06-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-05-10
      • 1970-01-01
      相关资源
      最近更新 更多