问题与Haskell的"做"

vuz*_*zun 4 syntax monads haskell

我编写了一个Haskell函数,用于计算给定列表中每个数字的阶乘,并将其打印到屏幕上.

factPrint list =
if null list
    then putStrLn ""
    else do putStrLn ((show.fact.head) list)
        factPrint (tail list)
Run Code Online (Sandbox Code Playgroud)

该功能有效,但我发现第三行有点令人困惑.为什么编译器(GHC)没有报告错误,因为在"putStrLn"(准?)函数之前没有"do"?如果我从第4行省略"do",则会按预期弹出错误.

我对Haskell及其方式都很陌生,所以如果我说的话过于愚蠢,请原谅我.

new*_*cct 11

do putStrLn ((show.fact.head) list)
   factPrint (tail list)
Run Code Online (Sandbox Code Playgroud)

实际上是另一种写作方式

putStrLn ((show.fact.head) list) >> factPrint (tail list)
Run Code Online (Sandbox Code Playgroud)

反过来,这意味着

putStrLn ((show.fact.head) list) >>= \_ -> factPrint (tail list)
Run Code Online (Sandbox Code Playgroud)

do符号串是这些单子在一起,如果没有这个丑陋的其他语法的便捷方式.

如果你里面只有一个语句do,那么你就不会把任何东西串在一起,这do是多余的.


Nat*_*ers 5

如果您是Haskell的新手,请考虑使用do类似ifC语言的类似于必需的大括号:

if (condition)
  printf("a"); // braces not required
else {
  printf("b"); // braces required
  finish();
}
Run Code Online (Sandbox Code Playgroud)

do 在Haskell中以相同的方式工作.


也许有助于查看factPrint的类型,然后重构使用模式匹配:

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

所以,如果factPrint返回IO (),和类型putStrLn ""IS IO (),那么它是完全合法的factPrint []平等putStrLn "".没有do必要 - 事实上,你可以说,factPrint [] = return ()如果你不想要尾随换行符.