我有以下代码段:
main = scotty 3000 $ do
get "/:word" $ do
beam <- param "word"
putStrLn "hello"
html $ mconcat ["<h1>Scotty, ", beam, " me up!</h1>"]
我明白,do
语句是如何工作的,它只是>>=
的语法糖,但上面的例子,怎么可能,我可以将do
块作为功能参数?
答案 0 :(得分:3)
让我们来定义
twice :: IO () -> IO ()
twice a = do
a
a
......或简称twice a = a>>a
。
你当然可以使用
Prelude> twice (putStrLn "hello")
hello
hello
...但是Haskellers喜欢保存parens并写twice $ putStrLn "hello"
。
您也可以像
一样使用它Prelude> twice $ putStrLn "hello" >> putStrLn "world"
hello
world
hello
world
现在,该monadic序列可以转换为do块:
Prelude> twice $ do{putStrLn "hello"; putStrLn "world"}
并且使用布局而不是大括号和分号,因此看起来如此:
Prelude> :{
Prelude| twice $ do
Prelude| putStrLn "hello"
Prelude| putStrLn "world"
Prelude| :}
hello
world
hello
world
答案 1 :(得分:1)
http://www.haskellforall.com/2014/10/how-to-desugar-haskell-code.html提供了几个示例来说明各种do
表达式是如何被删除的。
单一表达
do
beam <- param "word"
putStrLn "hello"
html $ mconcat ["<h1>Scotty, ", beam, " me up!</h1>"]
首先被递归地移植到多个嵌套表达式中:
do
beam <- param "word"
do putStrLn "hello"
html $ mconcat ["<h1>Scotty, ", beam, " me up!</h1>"]
内部使用>>
运算符进行desugars:
do
beam <- param "word"
(putStrLn "hello" >> html $ mconcat ["<h1>Scotty, ", beam, " me up!</h1>"])
使用>>=
生成的表达式desugars:
param "word" >>= (\beam -> (putStrLn "hello" >> html $ mconcat ["<h1>Scotty, ", beam, " me up!</h1>"])
此表达式被视为get "/:word"
的参数:
main = scotty 3000 $ do
get "/:word" $ param "word" >>= (\beam -> (putStrLn "hello" >> html $ mconcat ["<h1>Scotty, ", beam, " me up!</h1>"])
最后剩下的do
表达非常简单地去了
main = scotty 3000 $ get "/:word" $ param "word" >>= (\beam -> (putStrLn "hello" >> html $ mconcat ["<h1>Scotty, ", beam, " me up!</h1>"])
作为单行do
表达式只是包装表达式本身(do x = x
)。