On Mon, 4 Jun 2012, Andreas Abel wrote:
> Concerning the suggestion that when_ would be in sync with forM_ and whenM_
> I'd say: not really. forM_ and whenM_ discard the result of the monadic
> computation, while when and when_ do not even have such a result. They
> always just perform some monadic effect and return nothing.
What is whenM_ ? Do you mean mapM_ ?
> >> :: m () -> m b -> b
>> mapM_ :: (a -> m ()) -> [a] -> m ()
> forM_ :: [a] -> (a -> m ()) -> m ()
> sequence_ :: [m ()] -> m ()
> forever :: m () -> m ()
>> and many more, like zipWithM_, foldM_, replicateM_.
I would prefer these strict types, too.
Alternatively I have wondered in the past whether it might be a good idea
to generalize them to:
> mapM_ :: Monoid b => (a -> m b) -> [a] -> m b
> forM_ :: Monoid b => [a] -> (a -> m b) -> m b
> sequence_ :: Monoid b => [m b] -> m b
> forever :: Monoid b => m b -> m b
This would still propagate monadic result type () if the final monadic
action has result type ().
http://www.haskell.org/pipermail/haskell-cafe/2009-January/054243.html
> Sorry, but I think all these function have been given their maximal general
> type
>> ==> to be able to ignore a result of a monadic computation
>> ==> without further noise.
Since the addition of 'void' the noise has become acceptable for me.
I would follow a kind of "separation of concerns". Ignoring results is one
step and performing forM_, when etc. is the second step.
> In my opinion, the types of when and unless are not general enough, an that
> is, imho, just an accident of history. Because it is the type that inferred
> for the shortest definition, which is
>> when cond m = if cond then m else return ()
>> Please reevaluate my proposal to change to
>> when :: Bool -> m a -> m ()
> unless :: Bool -> m a -> m ()
>> in the light of the above arguments.
Last time I asked the question, what application you do have in mind. Is
your code cluttered with void's or do you just need it occasionally?