是否有一个 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
。
我有以下带有半群元素的 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
。