Perform Monadic Computation N times

I'm implementing a function to perform a monadic computation N times. I've written the following code.

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)

I get the following error.

: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 -> mt -> m [t]
at :260:13
Expected type: [mt]
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 :: mt (bound at :262:12)
performN :: Int -> mt -> m [t] (bound at :261:1)

I can't seem to figure out what I am doing wrong and how to fix it.


You've got doing something zero times right.

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

And you've got the first part of doing something n times right: do it once.

performN n m = do
  x1 <- m

But then all you have to do is do it n − 1 more times. No strange if stuff.

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

Too much stuff. n == 1 ? n-2 ? Why? Simpler!

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

如果你需要使用这个函数,而不是需要实践它,你应该使用Control.Monad.replicateM而不是自己重新实现它。

链接地址: http://www.djcxy.com/p/43046.html

上一篇: Collections.emptyList()返回一个List <Object>?

下一篇: 单次计算N次