是否有一个 Monad 收集结果并将其“映射”?

Is there a Monad which collects results and `mappend`s them?

我有以下带有半群元素的 Reader 模式:

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

我觉得我经常看到这种模式,我 强制性地 链接 monadic 调用,最后它们变成单个元素。

注意:我不想做 getA >>= getB >>= getC 因为 getB 不是 :: Element -> Reader Env Element

感觉像State Monad,用<>自动修改状态,但我不知道。

使用 monadic 代码对我来说还是很新鲜的。

runFunction = fmap mconcat . sequence $ [getA, getB, getC]

无论 monad 是什么。

fmap mconcat . sequence
  :: (Monoid b, Monad f, Traversable t) => t (f b) -> f b

List,[],是一个 Traversable。

对于半群,有 sconcat

WriterT monad 转换器可用于为每个动作建立一个幺半群值。

您可以使用 lift to wrap your Reader actions into the WriterT monad transformer, then move the result of each action into the monad's environment by using tell, sequence the actions, and then unwrap the result back to a single Reader action using execWriterT.

我的意思是:

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

如您所见,这可以推广到任何单子,而不仅仅是 Reader