如何解决Monad 挑战 - 一个遗漏的概括
我正在经历 The Monad Challenges。
在 A Missed Generalization 部分,我应该至少有这个代码(我已经删除了与问题无关的部分),其中 Gen
看起来很像 State Monad,
-- Imports and other stuff that hide Prelude
-- For instance,the do notation is NOT available at this stage of the challenges
type Gen a = Seed -> (a,Seed)
genTwo :: Gen a -> (a -> Gen b) -> Gen b
genTwo g f s = let (a,s') = g s
in f a s'
mkGen :: a -> Gen a
mkGen a s = (a,s)
generalB :: (a -> b -> c) -> Gen a -> Gen b -> Gen c
-- I've implemented it as follows and it works
generalB f a b s = let (x,s') = a s
(y,s'') = b s'
in (f x y,s'')
“作业”正文为
[...] 您可能没有在 generalB
方面实现 genTwo
。返回并查看您的 generalB
实现,如果您没有按照 genTwo
编写它,请立即执行并将其命名为 generalB2
。这样做应该可以摆脱生成器之间的状态线程。
我不清楚这个问题的解决方案应该是什么,特别是考虑到上面的段落没有提到mkGen
。假设我能够将 f
应用到 a
和 b
的内部,我仍然会得到 c
类型的东西,我必须将其推入 {{ 1}},如果没有 Gen
,或者没有明确使用 mkGen
(就像我在上面的实现中所做的那样),我不知道如何做到这一点。
即使假设文本暗示我应该使用 (,)
,我应该如何去摆脱状态线程?
通过一些编辑,我能够想出这个
mkGen
但我几乎不相信这是预期的解决方案,因为在我看来,它远非可读。此外,到目前为止,在挑战中达到这种形式比其他任何事情都难,但它毕竟只是机械性的,所以从理解 monad 的角度来看,它并没有真正构成困难,我相信,所以我我真的觉得我在这里走错了路,我需要一些帮助。
我想知道挑战的作者是否在 StackOverflow 上闲逛。
解决方法
您的解决方案可能接近预期的解决方案,尽管您可以通过对它进行 eta-expanding 使其更具可读性。您甚至可以考虑使用 do
表示法编写它,但仍使用 genTwo
和 mkGen
。
据我所知,mkGen
是一个“伪装的”return
函数,而 genTwo
同样是一个“伪装的”monadic 绑定(即 >>=
)。
generalB
(和generalB2
)的类型等价于liftM2
,其中is implemented like this:
liftM2 :: (Monad m) => (a1 -> a2 -> r) -> m a1 -> m a2 -> m r
liftM2 f m1 m2 = do { x1 <- m1; x2 <- m2; return (f x1 x2) }
也就是说,就 return
和 >>=
而言(您没有看到,因为它使用的是 do
语法)。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。