[英]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.