题
我写一个Haskell函数,计算在给定的列表并将其打印到屏幕阶乘每数目。
factPrint list =
if null list
then putStrLn ""
else do putStrLn ((show.fact.head) list)
factPrint (tail list)
在功能工作,但我发现第三行有点混乱。 为什么没有编译器(GHC)报告一个错误就可以了,因为没有“做”的“putStrLn”(准?)函数之前? 如果我省略“做”从第4行,如所预期的错误弹出。
我是很新的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
用于配合多种一元表达式在一起。它随后当仅由单个表达没有影响。
有关的,如果是良好形成的,即当时-子句和else从句具有相同的类型,仅需要。由于两个条款不得不类型IO ()
是这种情况。
在不关键字用于测序,如果 - 则 - 否则在Haskell不必包含do
在所有如果每个分支是一个语句例如
if a
then b
else c
您需要在您的示例do
因为你是你的else分支测序两个操作。如果省略do
那么factPrint(tail list)
声明被认为不是功能的一部分,因此为它遇到了一个意想不到的声明编译器会抱怨。
不隶属于 StackOverflow