Haskell:如何做一个循环

时间:2017-12-05 20:59:47

标签: haskell

我必须阅读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    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^...

2 个答案:

答案 0 :(得分:6)

您是否尝试过replicateM

  

replicateM n act执行n次行动,收集结果。

答案 1 :(得分:3)

这里有一些问题:

  1. 您将[y:ys]写为缺点,但Haskell中的缺点(:) :: a -> [a] -> [a]运算符,因此它是y : ys(y : ys)(括号之间)。如果您编写[y:ys],则将(y:ys)的结果换成新的单例列表;
  2. 您执行y <- a n + 1 次,因为使用Monads的原因之一可能是使用状态(例如,状态使用IO)的机器,这可能会产生意想不到的副作用;和
  3. 您使用的(replicateIO n-1 a)在Haskell中被解释为((replicateIO n)-(1 a))
  4. 但我认为最重要的方面是你在 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实际上是某些函数的语法糖可能是有益的。)