如何解决有Monad可以收集结果并将其“附加”吗?
我具有带有半群元素的阅读器以下模式:
runFunction :: Reader Env Element
runFunction = do
a <- getA
b <- getB
c <- getC
return $ a <> b <> c
getA :: Reader Env Element
处。
有没有办法:
runFunction = do
getA
getB
getC
我觉得我看到了很多这种模式,在这些命令中,我强制性地链接单子调用,它们最终变成一个元素。
注意:我不想做getA >>= getB >>= getC
,因为getB
不是:: Element -> Reader Env Element
感觉就像是State Monad,它会自动用<>
修改状态,但我不知道。
对我来说,使用单子代码仍然很新鲜。
解决方法
WriterT
monad变换器可用于在每个动作中建立一个单调值。
您可以使用lift
将Reader
动作包装到WriterT
monad转换器中,然后通过使用tell
将序列的每个动作的结果移动到monad的环境中操作,然后使用execWriterT
将结果解开为单个Reader
操作。
这是我的意思:
import Control.Monad.Writer
wrap :: (Monad m,Monoid w) => m w -> WriterT w m ()
wrap m = lift m >>= tell
unwrap :: (Monad m) => WriterT w m a -> m w
unwrap = execWriterT
runFunction :: Reader Env Element
runFunction = unwrap $ do
wrap getA
wrap getB
wrap getC
如您所见,这可以推广到任何monad,而不仅仅是Reader
。
runFunction = fmap mconcat . sequence $ [getA,getB,getC]
单子是什么。
fmap mconcat . sequence
:: (Monoid b,Monad f,Traversable t) => t (f b) -> f b
列表[]
是可遍历的。
对于Semigroups,有sconcat
。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。