[Haskell] Types of when and unless in Control.Monad
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
> 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 ().
> 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
> 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