我的(尝试的)iterateM 实现有什么问题?
我想实现一个函数 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我从您的签名中收集到的信息
是:第 n 个元素
iterateM f x
将是一个运行f
n
的操作> 次。这与迭代非常接近,我怀疑我们可以以此来实现它。iterate
给了我们一个b
列表,而我们想要一个m a
列表,所以我怀疑b = m a.
现在我们需要一种方法来转换
f :: a -> m a
变成ma ->; 类型的东西m a.
.幸运的是,这正是绑定的定义:所以:
为了将我们的初始
x :: a
转换为所需的m a
,我们可以使用return
>:所以:
点冻结来品尝。
What I gather from your signature:
Is that the
n
th elementiterateM f x
will be an action that runsf
n
times. This is very close toiterate
, I suspect we can implement it in terms of that.iterate
gives us a list ofb
s, and we want a list ofm a
s, so I suspectb = m a
.Now we need a way to transform
f :: a -> m a
into something of typem a -> m a
. Fortunately, that is exactly the definition of bind:So:
And to get our initial
x :: a
into the desiredm a
, we can usereturn
:So:
Pointfreeize to taste.
您对 iterateM 的递归使用迫使它位于列表 monad 中。您需要运行 iterateM 操作并返回其结果。
尝试:
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: