我的(尝试的)iterateM 实现有什么问题?

发布于 2024-12-07 10:50:06 字数 952 浏览 1 评论 0原文

我想实现一个函数 iterateM,其类型如下所示:

iterateM :: Monad m => (a -> m a) -> a -> [m a]

但是,我首先编写这个函数:

iterateM f x = f x >>= (\x' -> return x' : iterateM f x')

给我错误:

Could not deduce (m ~ [])
from the context (Monad m)
  bound by the type signature for
             iterateM :: Monad m => (a -> m a) -> a -> [m a]
  at main.hs:3:1-57
  `m' is a rigid type variable bound by
      the type signature for
        iterateM :: Monad m => (a -> m a) -> a -> [m a]
      at main.hs:3:1
Expected type: [a]
  Actual type: m a
In the return type of a call of `f'
In the first argument of `(>>=)', namely `f x'
In the expression: f x >>= (\ x' -> return x' : iterateM f x')

如果我删除我的类型签名,ghci 会告诉我函数的类型是:

iterateM :: Monad m => (a -> [a]) -> a -> [m a]

我在这里缺少什么?

I would like to implement a function, iterateM, whose type would look like this:

iterateM :: Monad m => (a -> m a) -> a -> [m a]

However, my first go at writing this function:

iterateM f x = f x >>= (\x' -> return x' : iterateM f x')

Gives me the error:

Could not deduce (m ~ [])
from the context (Monad m)
  bound by the type signature for
             iterateM :: Monad m => (a -> m a) -> a -> [m a]
  at main.hs:3:1-57
  `m' is a rigid type variable bound by
      the type signature for
        iterateM :: Monad m => (a -> m a) -> a -> [m a]
      at main.hs:3:1
Expected type: [a]
  Actual type: m a
In the return type of a call of `f'
In the first argument of `(>>=)', namely `f x'
In the expression: f x >>= (\ x' -> return x' : iterateM f x')

If I remove my type-signature, ghci tells me the type of my function is:

iterateM :: Monad m => (a -> [a]) -> a -> [m a]

What am I missing here?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

柠檬色的秋千 2024-12-14 10:50:06

我从您的签名中收集到的信息

iterateM :: (Monad m) => (a -> m a) -> a -> [m a]

是:第 n 个元素 iterateM f x 将是一个运行 f n 的操作> 次。这与迭代非常接近,我怀疑我们可以以此来实现它。

iterate :: (b -> b) -> b -> [b]

iterate 给了我们一个 b 列表,而我们想要一个 m a 列表,所以我怀疑 b = m a.

iterate :: (m a -> m a) -> m a -> [m a]

现在我们需要一种方法来转换 f :: a -> m a 变成 ma ->; 类型的东西m a..幸运的是,这正是绑定的定义:

(=<<) :: (Monad m) => (a -> m b) -> (m a -> m b)

所以:

\f -> iterate (f =<<) :: (a -> m a) -> m a -> [m a]

为了将我们的初始 x :: a 转换为所需的 m a,我们可以使用 return >:

return :: (Monad m) => a -> m a

所以:

iterateM f x = iterate (f =<<) (return x)

点冻结来品尝。

What I gather from your signature:

iterateM :: (Monad m) => (a -> m a) -> a -> [m a]

Is that the nth element iterateM f x will be an action that runs f n times. This is very close to iterate, I suspect we can implement it in terms of that.

iterate :: (b -> b) -> b -> [b]

iterate gives us a list of bs, and we want a list of m as, so I suspect b = m a.

iterate :: (m a -> m a) -> m a -> [m a]

Now we need a way to transform f :: a -> m a into something of type m a -> m a. Fortunately, that is exactly the definition of bind:

(=<<) :: (Monad m) => (a -> m b) -> (m a -> m b)

So:

\f -> iterate (f =<<) :: (a -> m a) -> m a -> [m a]

And to get our initial x :: a into the desired m a, we can use return:

return :: (Monad m) => a -> m a

So:

iterateM f x = iterate (f =<<) (return x)

Pointfreeize to taste.

梓梦 2024-12-14 10:50:06

您对 iterateM 的递归使用迫使它位于列表 monad 中。您需要运行 iterateM 操作并返回其结果。

尝试:

iterateM f x = do
      x' <- f x
      xs <- iterateM f x'
      return $ x':xs

Your recursive use of iterateM is forcing it to be in the list monad. You need to run the iterateM action and return its result.

Try:

iterateM f x = do
      x' <- f x
      xs <- iterateM f x'
      return $ x':xs
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文