我编写了一个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 ""
IS IO ()
,那么它是完全合法的factPrint []
平等putStrLn ""
.没有do
必要 - 事实上,你可以说,factPrint [] = return ()
如果你不想要尾随换行符.