multiset icon indicating copy to clipboard operation
multiset copied to clipboard

Convenience function mapM

Open pjljvandelaar opened this issue 6 years ago • 2 comments

As a user, I would like the monad version of map to be provided by the multiset library instead of having to define it locally each time I need it. Consequently, when a better implementation is possible, I don't have to change my code in many places.

MultiSet already offers the map function of signature Ord b => (a-> b) -> MultiSet.MultiSet a -> MultiSet.MultiSet b . Could you also offer something like

{-# LANGUAGE ScopedTypeVariables #-}
mapM :: forall a b m . (Ord b, Monad m) => (a-> m b) -> MultiSet.MultiSet a -> m (MultiSet.MultiSet b)
mapM f a = MultiSet.fromOccurList <$> mapM f' (MultiSet.toOccurList a)
          where f' :: (a, MultiSet.Occur) -> m (b, MultiSet.Occur)
                     f' (x,c) = do
                                      v <- f x
                                      return (v,c)

I use the naming convention: A postfix 'M' always stands for a function in the Kleisli category: The monad type constructor m is added to function results (modulo currying) and nowhere else. So, for example,

filter  ::              (a ->   Bool) -> [a] ->   [a]
filterM :: (Monad m) => (a -> m Bool) -> [a] -> m [a]

pjljvandelaar avatar Jun 04 '18 08:06 pjljvandelaar

It makes sense to add mapM. Especially because it exists for Map and Set from containers.

twanvl avatar Jun 04 '18 11:06 twanvl

Note that Data.Set in fact doesn't offer a mapM function, probably because mapM is usually defined in terms of a Traversable instance, which Set doesn't have – it isn't even a Functor.

sjakobi avatar Jul 20 '19 15:07 sjakobi