Haskell:如何进行循环

问题描述 投票:0回答:2

我必须读

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    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^...
haskell monads
2个回答
6
投票

你尝试过吗

replicateM

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


3
投票

这里有一些问题:

  1. 你将
    [y:ys]
    写为 cons,但 Haskell 中的 cons
    (:) :: a -> [a] -> [a]
    运算符,所以它是
    y : ys
    ,或
    (y : ys)
    (在括号之间)。如果你写
    [y:ys]
    ,你就会将
    (y:ys)
    的结果包装成一个新的单例列表;
  2. 您执行
    y <- a
    n+1 次,因为使用 Monad 的原因之一可能是使用 state(例如带有
    IO
    的机器状态),这可能会产生意想不到的副作用;和
  3. 你使用
    (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

语法。例如,我们可以使用守卫代替 if-

then
-
else
:

replicateIO n a | n < 0 = return [] | otherwise = do y <- a ys <- replicateIO (n-1) a return (y:ys)

我们可以做一些进一步的改进(甚至省略 
do

符号,但我认为首先认识到

do
实际上是某些函数的语法糖可能是有益的)。
    

© www.soinside.com 2019 - 2024. All rights reserved.