执行 Monadic 计算 N 次

Perform Monadic Computation N times

我正在实现一个函数来执行 N 次单子计算。我写了下面的代码。

performN :: Monad m => Int -> m t -> m [t]
performN 0 m = return []
performN n m = 
  do x1<- m
     x2<- if n == 1 then return [] else (m:performN (n-2) m)
     return (x1:x2)

我收到以下错误。

:264:44: error:
• Couldn't match type ‘m’ with ‘[]’
‘m’ is a rigid type variable bound by
the type signature for:
performN :: forall (m :: * -> *) t. Monad m => Int -> m t -> m [t]
at :260:13
Expected type: [m t]
Actual type: m [t]
• In the second argument of ‘(:)’, namely ‘performN (n - 2) m’
In the expression: (m : performN (n - 2) m)
In a stmt of a 'do' block:
x2 <- if n == 1 then return [] else (m : performN (n - 2) m)
• Relevant bindings include
m :: m t (bound at :262:12)
performN :: Int -> m t -> m [t] (bound at :261:1)

我似乎无法弄清楚我做错了什么以及如何解决它。

东西太多了。 n == 1n-2?为什么?更简单!

performN :: Monad m => Int -> m t -> m [t]
performN 0 _ = return []
performN n m =
  do x  <- m
     xs <- performN (n-1) m
     return $ x:xs

你做对了零次。

performN :: Monad m => Int -> m t -> m [t]
performN 0 m = return []

你已经掌握了正确做某事 n 次的第一部分:做一次。

performN n m = do
  x1 <- m

但是你所要做的就是再做 n − 1 次。没有什么奇怪的 if 东西。

performN n m = do
  x1 <- m
  x2 <- performN (n - 1) m
  return (x1 : x2)

如果您需要使用此功能,而不是为了练习而需要实现它,您应该直接使用 Control.Monad.replicateM 而不是自己重新实现它。