[Haskell] Types of when and unless in Control.Monad
Andreas Abel
andreas.abel at ifi.lmu.de
Tue Jun 5 14:52:20 CEST 2012
On 06/04/2012 09:25 PM, Henning Thielemann wrote:
>
> 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_ ?
Probably...
>> >> :: 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.
Ok, well, then you probably would not want to use mapM_ and the like,
but instead
mapM (void . f) l
which instantiates the type b to (), giving above typings.
> 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
But that would not be backwards compatible.
>> 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.
Ok. But I am really surprised that an operation should not get the
maximally sensible type.
It seems that I like to think of () as a terminal type (in the sense of
category theory), but this intuition is not shared by everyone. [I am
aware that () is NOT the terminal type in Haskell.]
>> 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?
The application is that I have a function that provides a resource that
may be present or not. If it is not present, an exception is thrown
(that is the monadic effect). If I am just interested in checking the
presence of the resource, I can call this function in a do-block. But I
am not allowed to call it in a 'when', without 'void'ing it. That is
counterintuitive.
To reconcile the 'strict' vs. 'liberal' programmers, it seems that
library functions need to have different types depending on whether
-fwarn-unused-do-bind
is set or not...
Cheers,
Andreas
--
Andreas Abel <>< Du bist der geliebte Mensch.
Theoretical Computer Science, University of Munich
Oettingenstr. 67, D-80538 Munich, GERMANY
andreas.abel at ifi.lmu.de
http://www2.tcs.ifi.lmu.de/~abel/
More information about the Libraries
mailing list