我在试着做一个函数来计算一个数的阶乘。它在作业中标出了一个错误,我不知道如何改正。
for list action = mapM_ action list
main :: IO Int
main = do
x <- getLine
for [1..read x] (\ i -> do
let tmp = 0
tmp <- tmp*i
)
return (tmp)
2条答案
按热度按时间f5emj3cl1#
首先,关于循环的说明。我猜是
for_
Haskell没有任何循环关键字,但它的monad范式足够灵活,因此它们可以作为库函数实现。但是,Haskell没有可变变量。所以像
tmp <- tmp*i
这样的东西永远都没有意义。(N.B.,你可以写
let tmp = tmp*i
,但不要这样做。它没有完成任何有用的事情;它不是更新变量,而是 * 定义 * 一个变量,但是用一个无意义的循环定义来引用它自己的结果,即这只是一个非终止计算。好吧,关于没有可变变量的说法并不完全正确。这些也可以从标准库中获得,它们被称为
IORef
s。它们不能用<-
或=
语法更新,但可以用Data.IORef
模块中定义的IO
操作更新。以下方法确实有效:请注意,没有
return
。在Haskell中,return
不是一个关键字(* 注意到主题了吗?* )而只是一个函数,它将一个纯值(在本例中为Int
)注入到一个一元动作(在本例中为IO Int
)中。但是阅读IORef
本身已经是一个不纯的动作,因此您应该简单地将其用作最后一行。从
main
返回一个值可能不是你想要的(返回值被忽略);我想你应该把它印出来:好吧,这就是你的问题的字面解决方案。
然而,强烈建议 * 不要 * 使用
IORef
来处理类似的事情。一般来说,Haskell的整个哲学是避免像突变这样的副作用。相反,您应该通过递归定义函数,并且只在最后使用IO
来打印完整的结果。有很多这样的例子,一个幽默的例子是The Evolution of a Haskell Programmer。66bbxpm52#
Haskell是一种函数式语言。这些语言的一个方面是变量是 * 不可变的 *:一旦赋值,你就永远不能改变这个值。
因此,Haskell没有内置的
for
循环等。它的“主力”是 recursion:我们递归直到确定某个值。对于阶乘情况,这看起来像:然后main可以看起来像这样:
或更短: