嵌套做语法

jhe*_*dus 4 monads haskell

这个问题中,Will的回答说明了以下代码(让我们称之为code A):

reverse2lines :: IO () 
reverse2lines = 
 do line1 <- getLine 
    line2 <- getLine
    putStrLn (reverse line2) 
    putStrLn (reverse line1)
Run Code Online (Sandbox Code Playgroud)

可以转换成以下(让我们称之为code B):

reverse2lines = 
 do { line1 <- getLine ;
      do { line2 <- getLine ;
           do { putStrLn (reverse line2) ;
                do { putStrLn (reverse line1) } } } }
Run Code Online (Sandbox Code Playgroud)

我很迷惑.例如,我理解这一点

addOneInt :: IO () 
addOneInt = do line <- getLine
               putStrLn (show (1 + read line :: Int))
Run Code Online (Sandbox Code Playgroud)

可以转化为:

addOneInt' :: IO ()
addOneInt' = getLine >>= \line ->
             putStrLn (show ( 1 + read line :: Int))  
Run Code Online (Sandbox Code Playgroud)

但我不明白嵌套do转换是如何工作的.换句话说,我不明白一个人是怎么code A来的code B?管理这种转变的规则是什么?

这些规则在哪里描述/解释/指定?

有人可以用这个(转化)codeA来解释这里发生了codeB什么吗?

例如,什么do { command1; do {command2 } }意思?我该怎么解释呢?它的定义是什么?

换一种说法,

有什么区别

do {command1;command2}

do {command1; do {command2}}

此外,有什么区别

do {command1; do{command2};command3}

do {command1;do {command2; do {command3}}}

谢谢阅读.

Tik*_*vis 5

只需将do表达式完全分开处理:嵌套它们并不会改变它们的去除方式.举个例子,我们可以从底线开始:

reverse2lines = 
 do { line1 <- getLine ;
      do { line2 <- getLine ;
           do { putStrLn (reverse line2) ;
                putStrLn (reverse line1) } } }
Run Code Online (Sandbox Code Playgroud)

那么下一个:

reverse2lines = 
 do { line1 <- getLine ;
      do { line2 <- getLine ;
           putStrLn (reverse line2) >> putStrLn (reverse line1) } }
Run Code Online (Sandbox Code Playgroud)

事实上,这就像:

reverse2lines = 
 do { line1 <- getLine ;
      do { line2 <- getLine ;
           putStrLn (reverse line2)
           putStrLn (reverse line1) } }
Run Code Online (Sandbox Code Playgroud)

然后我们可以将内部剩余do变为lambda:

reverse2lines = 
 do { line1 <- getLine ;
      getLine >>= \ line2
       putStrLn (reverse line2) >>
       putStrLn (reverse line1)  }
Run Code Online (Sandbox Code Playgroud)

然后,如果我们倒退,我们会发现它与以下相同:

reverse2lines = 
 do { line1 <- getLine ;
      line2 <- getLine ;
      putStrLn (reverse line2) ;
      putStrLn (reverse line1)  }
Run Code Online (Sandbox Code Playgroud)

因此,正如您通过整个示例所看到的,嵌套版本与平面版本相同.事实上,如果你只看一下desugaring do表达式的规则(我们已经看到了重要的那些),你会发现像这样嵌套它们不会改变任何东西.

事实上,这是非常自然的,因为dodesugared 的方式是递归定义的:每次我们desugar一行,我们递归跟随它的所有行,就好像它们是另一个do表达式.