2

在下面的代码中,第 4 行,我有一个表达式夹在 do 块中的两个 IO 操作之间:

  1 doubleX :: (Show x, Num x) => x -> IO ()                                                                                                                                                                                          
  2 doubleX x = do                                                                                                                                                                                                                    
  3   putStrLn ("I will now double " ++ (show x))                                                                                                                                                                                     
  4   let double = x * 2                                                                                                                                                                                                              
  5   putStrLn ("The result is " ++ (show double))

我将 do 表示法理解为使用 >>= 或 >> 将单子操作链接在一起。但是当你在两者之间有一个表达式时,它是如何工作的?您不能只使用 >> 将 3-5 行粘合在一起。

4

1 回答 1

6

我将从我非常相似的答案here(尽管可能不是重复的,因为该问题没有明确处理let)。

报告给出了从 do 语法到内核 Haskell 的完整翻译;与您的问题相关的部分是:

do {e}                = e
do {e;stmts}          = e >> do {stmts}
do {let decls; stmts} = let decls in do {stmts}

所以你的代码像这样去糖:

doubleX x = do                                                                                                                                                                                                                    
  putStrLn ("I will now double " ++ (show x))                                                                                                                                                                                     
  let double = x * 2                                                                                                                                                                                                              
  putStrLn ("The result is " ++ (show double))

==> do {e;stmts} rule

doubleX x =
  putStrLn ("I will now double " ++ (show x)) >> do
  let double = x * 2                                                                                                                                                                                                              
  putStrLn ("The result is " ++ (show double))

==> do {let decls; stmts} rule

doubleX x =
  putStrLn ("I will now double " ++ (show x)) >>
  let double = x * 2 in do
  putStrLn ("The result is " ++ (show double))

==> do {e} rule

doubleX x =
  putStrLn ("I will now double " ++ (show x)) >>
  let double = x * 2 in
  putStrLn ("The result is " ++ (show double))
于 2017-07-30T20:06:51.510 回答