2017-09-25 55 views
0

我有下面的代碼片段:瞭解做語句作爲參數

main = scotty 3000 $ do 
    get "/:word" $ do 
     beam <- param "word" 
     putStrLn "hello" 
     html $ mconcat ["<h1>Scotty, ", beam, " me up!</h1>"] 

我明白,do聲明是如何工作的,它只是一個語法糖>>=,但上面的例子,怎麼會這樣,那我可以通過do塊作爲函數參數嗎?

+0

高階函數將函數作爲函數參數 – raam86

+2

您能更好地定義什麼讓您感到困惑嗎?你可以通過例如。 '(bar 7 + 3)'作爲一個適當類型的函數'foo'的參數。 *爲什麼*不能將'(x >> = baz z)'作爲參數傳遞給另一個適當類型的函數? –

+0

'do'不是'>> ='本身的語法糖。 –

回答

3

讓我們來定義

twice :: IO() -> IO() 
twice a = do 
    a 
    a 

...或短twice a = a>>a

你當然可以使用這個喜歡

Prelude> twice (putStrLn "hello") 
hello 
hello 

...但Haskellers寧願節省括號,寫twice $ putStrLn "hello"

您還可以使用它像

Prelude> twice $ putStrLn "hello" >> putStrLn "world" 
hello 
world 
hello 
world 

現在,單子序列可轉換爲一個do塊:

Prelude> twice $ do{putStrLn "hello"; putStrLn "world"} 

,並與佈局而不是括號&分號,這看起來這樣的:

Prelude> :{ 
Prelude| twice $ do 
Prelude| putStrLn "hello" 
Prelude| putStrLn "world" 
Prelude| :} 
hello 
world 
hello 
world 
1

http://www.haskellforall.com/2014/10/how-to-desugar-haskell-code.html提供了幾個例子來說明w各種各樣的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表達平凡desugars到

main = scotty 3000 $ get "/:word" $ param "word" >>= (\beam -> (putStrLn "hello" >> html $ mconcat ["<h1>Scotty, ", beam, " me up!</h1>"]) 

爲單行do表達式本身就是包裹的表達式(do x = x)。