我想在 Haskell 中按顺序组合两个 monad 动作,丢弃第二个产生的任何值,并将参数传递给这两个动作。
在我看来,这听起来像是Reader
——函数类型r -> m a
与 同构ReaderT r m a
,并且 monad 通过将相同的r
值隐式插入所有“洞”来工作。例如:
import Control.Applicative
import Control.Monad.Reader
example :: IO String
example = getLine >>= discarding putStrLn
discarding :: Monad m => (a -> m b) -> a -> m a
discarding action = runReaderT (ReaderT action *> ask)
你想要的运算符是这样的:
action `thingy` extra = action >>= discarding extra
但当然discarding
有一个更简单的实现:
discarding :: Applicative f => (a -> f b) -> a -> f a
discarding action a = action a *> return a
...所以最后我认为这真的是代码高尔夫。但是在一个更复杂的程序中,这是一个更大规模的常见模式,它可能值得一试。基本上,如果您有:
a0 :: r -> m a0
a1 :: r -> m a1
.
.
.
an :: r -> m an
然后是这样的:
ReaderT a0 :: ReaderT r m a0
ReaderT a1 :: ReaderT r m a1
.
.
.
ReaderT an :: ReaderT r m an
接着:
runReaderT (ReaderT a0 <* ReaderT a1 <* ... <* ReaderT an) :: r -> m a0