[Haskell] Types of when and unless in Control.Monad

Henning Thielemann lemming at henning-thielemann.de
Tue Jun 5 22:00:20 CEST 2012

On Tue, 5 Jun 2012, Andreas Abel wrote:

>> 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

This would result in 'm [()]' not in 'm ()'. I could e.g. get information 
from the number elements in the [()] list, but () tells me nothing. Thus 
they are really different.

>> 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.

Not completely. You may need additional type annotations.

>> 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.

There are other functions, like 'asTypeOf' that have intentionally not the 
most general type. :-)

My concern is safety and safety means to intentionally forbid things. 
That's why I prefer Haskell to C or MatLab. E.g. C by default ignores 
results from functions if they are not used. But this way, people may 
write (a==b;) instead of (a=b;) without noticing the mistake.

> 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.

How do you free the resource if you ignore the returned handle?

If checking for an exception this way is a common pattern in your code, 
how about writing a function that catches the exception and run some code, 
if there is no exception? It might have a signature like

whenAvailable :: IO resource -> IO () -> IO ()

and might be used like this

whenAvailable getResource $ do

> 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...

Something like a type system that does not only support 'correct' and 
'wrong', but also 'suspect', would solve the problem. :-)

More information about the Libraries mailing list