簡體   English   中英

問題與Haskell的“做”

[英]Issue with Haskell's “do”

我編寫了一個Haskell函數,用於計算給定列表中每個數字的階乘,並將其打印到屏幕上。

factPrint list =
if null list
    then putStrLn ""
    else do putStrLn ((show.fact.head) list)
        factPrint (tail list)

該功能有效,但我發現第三行有點令人困惑。 為什么編譯器(GHC)沒有報告錯誤,因為在“putStrLn”(准?)函數之前沒有“do”? 如果我從第4行省略“do”,則會按預期彈出錯誤。

我對Haskell及其方式都很陌生,所以如果我說的話過於愚蠢,請原諒我。

do putStrLn ((show.fact.head) list)
   factPrint (tail list)

實際上是另一種寫作方式

putStrLn ((show.fact.head) list) >> factPrint (tail list)

反過來,這意味着

putStrLn ((show.fact.head) list) >>= \_ -> factPrint (tail list)

do記號是串起這些單子在一起,如果沒有這個丑陋的其他語法的便捷方式。

如果你在do只有一個語句,那么你就不會把任何東西串在一起, do是多余的。

如果你是新來的Haskell,認為do類似於需要括號后if在一個類似C語言:

if (condition)
  printf("a"); // braces not required
else {
  printf("b"); // braces required
  finish();
}

do的工作在Haskell同樣的方式。


也許有助於查看factPrint的類型,然后重構使用模式匹配:

factPrint :: [Int] -> IO ()
factPrint [] = putStrLn ""
factPrint list = do
  putStrLn (show.fact.head) list
  factPrint (tail list)

因此,如果factPrint返回IO () ,並且putStrLn ""的類型是IO () ,則factPrint []等於putStrLn ""是完全合法的。 沒有do必需的-事實上,你可以只說factPrint [] = return () ,如果你不想尾隨換行符。

do用於將多個monadic表達式綁定在一起。 只有一個表達式后面沒有效果。

對於if格式良好,只需要then子句和else子句具有相同的類型。 由於兩個子句都具有類型IO ()因此就是這種情況。

do關鍵字用於排序,如果每個分支是單個語句,則Haskell中的if-then-else不必包含do ,例如。

if a
  then b
  else c

當您在其他分支上對兩個操作進行排序時,您需要在示例中do 如果省略do那么factPrint(tail list)語句被認為不是函數的一部分,因此編譯器會因為遇到意外語句而抱怨。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM