I want to consistently compose two monad actions in Haskell, discarding any value created by the second, and passing an argument to both actions.
It sounds like Reader to me - the function type r -> ma is isomorphic to ReaderT rma , and the monad works by implicitly taking the same value of r into all the "holes". For example:
import Control.Applicative import Control.Monad.Reader example :: IO String example = getLine >>= discarding putStrLn discarding :: Monad m => (a -> mb) -> a -> ma discarding action = runReaderT (ReaderT action *> ask)
The statement you want is something like:
action `thingy` extra = action >>= discarding extra
But of course, discarding has a simpler implementation:
discarding :: Applicative f => (a -> fb) -> a -> fa discarding action a = action a *> return a
... therefore, in the end, I think it's really code golf. But in a more complex program, where it is a larger picture on a wider scale, it may be worth it. Basically, if you have:
a0 :: r -> m a0 a1 :: r -> m a1 . . . an :: r -> m an
It follows that:
ReaderT a0 :: ReaderT rm a0 ReaderT a1 :: ReaderT rm a1 . . . ReaderT an :: ReaderT rm an
And then:
runReaderT (ReaderT a0 <* ReaderT a1 <* ... <* ReaderT an) :: r -> m a0
Luis casillas
source share