Skip to content

Additions to Control.Monad

I'd like to propose the following additions/changes to Control.Monad: mfilter can be generalised:

gen_mfilter :: Monad m => (a -> m ()) -> m a -> m a
gen_mfilter f ma = (\a -> liftM (const a) (f a)) =<< ma

Now we obtain the old mfilter as

gen_mfilter.(guard.)

Further, m () is a monoid for every monad, which would cause conflicts for [()], to name one example. (The usual monoid instance of [()] is addition of natural numbers, while the monadic monoid instance is multiplication.) More generally, the monoid m () acts on every type m a in the following way:

mtimes :: Monad m => m () -> m a -> m a
mtimes = gen_mfilter.const = liftM2 (flip const)
when = mtimes.guard

For example, each element of a list can be duplicated like this:

mtimes [(),()]

To see why these functions are useful, consider the DDist monad of the ProbabilityMonads package: Since DDist () is essentially the monoid of real numbers with multiplication, gen_mfilter f updates a distribution by multiplying the weight of x by f x. Another example is the state monad ST s, where type (a -> ST s ()) is essentially a -> s -> s, so these functions encode changes that, when used with gen_mfilter alter state, not the value.

Trac metadata
Trac field Value
Version 7.8.2
Type FeatureRequest
TypeOfFailure OtherFailure
Priority low
Resolution Unresolved
Component libraries/base
Test case
Differential revisions
BlockedBy
Related
Blocking
CC ekmett, hvr
Operating system
Architecture
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information