我必须阅读n
次,然后将其全部列入清单。我有以下代码但它不起作用。任何Haskell /功能专家都可以给我一个亮点?
replicateIO n a = do y <- a
if n < 0
then return []
else do ys <- (replicateIO n-1 a)
return [y:ys]
编译错误:
tres.hs:1:1: error:
Couldn't match type ‘(->) t0’ with ‘[]’
Expected type: t -> [[a]]
Actual type: t -> t0 -> [[a]]
|
1 | replicateIO n a = if n < 0 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^...
答案 0 :(得分:6)
您是否尝试过replicateM
?
replicateM n act
执行n
次行动,收集结果。
答案 1 :(得分:3)
这里有一些问题:
[y:ys]
写为缺点,但Haskell中的缺点是(:) :: a -> [a] -> [a]
运算符,因此它是y : ys
或(y : ys)
(括号之间)。如果您编写[y:ys]
,则将(y:ys)
的结果换成新的单例列表; y <- a
n + 1 次,因为使用Monads的原因之一可能是使用状态(例如,状态使用IO
)的机器,这可能会产生意想不到的副作用;和(replicateIO n-1 a)
在Haskell中被解释为((replicateIO n)-(1 a))
。但我认为最重要的方面是你在 Haskell语法中编写命令式程序。 Haskell是一种功能编程语言。这意味着不同的范例。我认为首先编写一些不能使用monad(和do
表示法)的程序可能会更好。
话虽如此,我们可以使用上述言论来解决问题中的问题:
replicateIO n a = if n < 0
then return []
else do y <- a
ys <- replicateIO (n-1) a
return (y:ys)
虽然这解决了问题,但它并不是非常优雅且 Haskell-ish 语法。例如,我们可以使用警卫代替if
- then
- else
:
replicateIO n a | n < 0 = return []
| otherwise = do
y <- a
ys <- replicateIO (n-1) a
return (y:ys)
我们可以进一步改进(甚至省略do
符号,但我认为首先发现do
实际上是某些函数的语法糖可能是有益的。)