gpt4 book ai didi

haskell - 嵌套 do 语法

转载 作者:行者123 更新时间:2023-12-02 17:04:55 25 4
gpt4 key购买 nike

this问题 Will 的回答指出以下代码(我们称之为代码 A):

reverse2lines :: IO () 
reverse2lines =
do line1 <- getLine
line2 <- getLine
putStrLn (reverse line2)
putStrLn (reverse line1)

可以转换为以下内容(我们称之为代码B):

reverse2lines = 
do { line1 <- getLine ;
do { line2 <- getLine ;
do { putStrLn (reverse line2) ;
do { putStrLn (reverse line1) } } } }

我很困惑。例如,我理解

addOneInt :: IO () 
addOneInt = do line <- getLine
putStrLn (show (1 + read line :: Int))

可以转化为:

addOneInt' :: IO ()
addOneInt' = getLine >>= \line ->
putStrLn (show ( 1 + read line :: Int))

但我不明白嵌套的 do 转换是如何工作的。换句话说,我不明白如何从 code A 到达 code B ?管理这种转变的规则是什么?

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

有人可以解释一下这个(codeAcodeB)转换发生了什么吗?

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

换句话说,

有什么区别

执行 {command1;command2}

执行{命令1;执行 {command2}}

此外,有什么区别

执行{命令1; do{command2};command3}

do {命令1;do {命令2;执行 {command3}}}

感谢您的阅读。

最佳答案

只需完全单独对待 do 表达式即可:嵌套它们不会改变它们的脱糖方式。对于您的示例,我们可以从底线开始:

reverse2lines = 
do { line1 <- getLine ;
do { line2 <- getLine ;
do { putStrLn (reverse line2) ;
putStrLn (reverse line1) } } }

然后是下一个:

reverse2lines = 
do { line1 <- getLine ;
do { line2 <- getLine ;
putStrLn (reverse line2) >> putStrLn (reverse line1) } }

事实上,就像:

reverse2lines = 
do { line1 <- getLine ;
do { line2 <- getLine ;
putStrLn (reverse line2)
putStrLn (reverse line1) } }

然后我们可以将内部剩余的 do 转换为 lambda:

reverse2lines = 
do { line1 <- getLine ;
getLine >>= \ line2
putStrLn (reverse line2) >>
putStrLn (reverse line1) }

然后,如果我们向后看,我们会发现它与以下内容相同:

reverse2lines = 
do { line1 <- getLine ;
line2 <- getLine ;
putStrLn (reverse line2) ;
putStrLn (reverse line1) }

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

事实上,这是很自然的,因为 do 的脱糖方式是递归定义的:每次我们对一行进行脱糖时,我们都会递归其后面的所有行,就好像它们是另一个 do 表达式。

关于haskell - 嵌套 do 语法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23090948/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com