执行Monadic计算N次

时间:2017-09-18 12:35:22

标签: haskell monads

我正在实现一个函数来执行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:错误:
      •无法将类型'm'与'[]'匹配         'm'是一个刚性类型变量,由           类型签名:
            performN :: forall(m :: * - &gt; *)t。 Monad m =&gt; Int - &gt; m t - &gt; m [t]
          at:260:13
        预期类型:[m t]
          实际类型:m [t]
      •在'(:)'的第二个参数中,即'performN(n - 2)m'
        在表达式中:(m:performN(n-2)m)
        在'do'区块中:           x2&lt; - 如果n == 1则返回[] else(m:performN(n - 2)m)
      •相关约束包括
          m :: m t(约束:262:12)
          performN :: Int - &gt; m t - &gt; m [t](约束于:261:1)

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

3 个答案:

答案 0 :(得分:8)

你做了零次正确的事。

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)

答案 1 :(得分:4)

太多的东西。 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

答案 2 :(得分:0)

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