
Hi all, I'm having some trouble with IO functions and exceptions. When I call an IO function in Haskell, I feel very uncomfortable, because you never know what kind of exceptions your function may throw. There are a lot of cases where thrown exceptions are not specified in the documentation. What's worse, there are cases where it's impossible to catch thrown exceptions in a safe way. Example to not knowing what exceptions may be thrown: http://hackage.haskell.org/package/base-4.6.0.1/docs/Control-Concurrent-Chan... `readChan` blocks the thread until it reads something. But what happens when channel is closed while one thread is blocked to read? It's not mentioned in the documentation and it's not specified in terms of types. (e.g. by using Either, Maybe or similar) Example to not being able to catch the exception: http://hackage.haskell.org/package/network-2.6.0.2/docs/Network-Socket.html `recvFrom` blocks the thread until it reads something. However, what happens if socket is closed while `recvFrom` is blocking to read? Similar to `readChan`, we can't know this. What's worse is this: sockets have a `SO_RCVTIMEO` option, a timeout value for `recv_from` calls. What happens when we set that using `setSocketOption` in the same module and call `recvFrom` is unknown. This is really horrible, because a timeout exception is really something that you'd like to catch. Example: I have a thread that listens from a socket and handles some other events. I want to stop listening the socket after every second and handle events, then return listening the socket. But I can't know what it throws when timeout happens, so I have to catch all exceptions, which is horrible for a lot of reasons. I was wondering if I'm doing something wrong. I'm sure we can find a lot of cases like these and I feel like libraries are not designed very good for errors/exceptions. So I'd like to get some ideas/suggestions about this. Am I doing something wrong or did I misunderstand something? Should we improve the libraries for better types/error handling? Am I only one here that has problems with those functions? Thanks.

Let's say you knew what exceptions could be thrown. What would you do differently then? Typically, if it's a command-line app and something unexpected happens, you simply present the error to the user. That's what exceptions do already without any effort from you. If it's a server app, you catch exceptions at a certain point, log them, maybe give some feedback to the client and proceed with the other requests. In order to do that, you don't really need to know the set of all possible exceptions.
`readChan` blocks the thread until it reads something. But what happens when channel is closed while one thread is blocked to read?
What do you mean by "channel is closed"? Channels don't get closed; there's no function to do that. It's possible that your blocked thread has the only remaining reference to the channel; in that case, the deadlock may (or may not) be detected, and an exception will be thrown in the former case.
Example to not being able to catch the exception: http://hackage.haskell.org/package/network-2.6.0.2/docs/Network-Socket.html `recvFrom` blocks the thread until it reads something. However, what happens if socket is closed while `recvFrom` is blocking to read? Similar to `readChan`, we can't know this. What's worse is this: sockets have a `SO_RCVTIMEO` option, a timeout value for `recv_from` calls. What happens when we set that using `setSocketOption` in the same module and call `recvFrom` is unknown. This is really horrible, because a timeout exception is really something that you'd like to catch. Example: I have a thread that listens from a socket and handles some other events. I want to stop listening the socket after every second and handle events, then return listening the socket. But I can't know what it throws when timeout happens, so I have to catch all exceptions, which is horrible for a lot of reasons.
It sounds like you're trying to write C-style in Haskell, which is probably not the best way to do it. More Haskelly way would be to: 1. Use Network instead of Network.Socket and take advantage of GHC's IO manager. That means that you'll be using something like epoll instead of recvfrom under the hood. 2. Instead of manually multiplexing several things into one thread (listening on the socket and "handling some other events"), do that in different threads. 3. If you do need a timeout (not for multiplexing, but for a genuine timeout), use System.Timeout. Roman

In the other side, this package does exactly what you want (I think).
2014-11-09 14:11 GMT+01:00 Roman Cheplyaka
Let's say you knew what exceptions could be thrown. What would you do differently then?
Typically, if it's a command-line app and something unexpected happens, you simply present the error to the user. That's what exceptions do already without any effort from you.
If it's a server app, you catch exceptions at a certain point, log them, maybe give some feedback to the client and proceed with the other requests. In order to do that, you don't really need to know the set of all possible exceptions.
`readChan` blocks the thread until it reads something. But what happens when channel is closed while one thread is blocked to read?
What do you mean by "channel is closed"? Channels don't get closed; there's no function to do that.
It's possible that your blocked thread has the only remaining reference to the channel; in that case, the deadlock may (or may not) be detected, and an exception will be thrown in the former case.
Example to not being able to catch the exception:
http://hackage.haskell.org/package/network-2.6.0.2/docs/Network-Socket.html
`recvFrom` blocks the thread until it reads something. However, what happens if socket is closed while `recvFrom` is blocking to read? Similar to `readChan`, we can't know this. What's worse is this: sockets have a `SO_RCVTIMEO` option, a timeout value for `recv_from` calls. What happens when we set that using `setSocketOption` in the same module and call `recvFrom` is unknown. This is really horrible, because a timeout exception is really something that you'd like to catch. Example: I have a thread that listens from a socket and handles some other events. I want to stop listening the socket after every second and handle events, then return listening the socket. But I can't know what it throws when timeout happens, so I have to catch all exceptions, which is horrible for a lot of reasons.
It sounds like you're trying to write C-style in Haskell, which is probably not the best way to do it.
More Haskelly way would be to:
1. Use Network instead of Network.Socket and take advantage of GHC's IO manager. That means that you'll be using something like epoll instead of recvfrom under the hood. 2. Instead of manually multiplexing several things into one thread (listening on the socket and "handling some other events"), do that in different threads. 3. If you do need a timeout (not for multiplexing, but for a genuine timeout), use System.Timeout.
Roman _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
-- Alberto.

This one:
https://hackage.haskell.org/package/control-monad-exception
2014-11-09 14:20 GMT+01:00 Alberto G. Corona
In the other side, this package does exactly what you want (I think).
2014-11-09 14:11 GMT+01:00 Roman Cheplyaka
: Let's say you knew what exceptions could be thrown. What would you do differently then?
Typically, if it's a command-line app and something unexpected happens, you simply present the error to the user. That's what exceptions do already without any effort from you.
If it's a server app, you catch exceptions at a certain point, log them, maybe give some feedback to the client and proceed with the other requests. In order to do that, you don't really need to know the set of all possible exceptions.
`readChan` blocks the thread until it reads something. But what happens when channel is closed while one thread is blocked to read?
What do you mean by "channel is closed"? Channels don't get closed; there's no function to do that.
It's possible that your blocked thread has the only remaining reference to the channel; in that case, the deadlock may (or may not) be detected, and an exception will be thrown in the former case.
Example to not being able to catch the exception:
http://hackage.haskell.org/package/network-2.6.0.2/docs/Network-Socket.html
`recvFrom` blocks the thread until it reads something. However, what happens if socket is closed while `recvFrom` is blocking to read? Similar to `readChan`, we can't know this. What's worse is this: sockets have a `SO_RCVTIMEO` option, a timeout value for `recv_from` calls. What happens when we set that using `setSocketOption` in the same module and call `recvFrom` is unknown. This is really horrible, because a timeout exception is really something that you'd like to catch. Example: I have a thread that listens from a socket and handles some other events. I want to stop listening the socket after every second and handle events, then return listening the socket. But I can't know what it throws when timeout happens, so I have to catch all exceptions, which is horrible for a lot of reasons.
It sounds like you're trying to write C-style in Haskell, which is probably not the best way to do it.
More Haskelly way would be to:
1. Use Network instead of Network.Socket and take advantage of GHC's IO manager. That means that you'll be using something like epoll instead of recvfrom under the hood. 2. Instead of manually multiplexing several things into one thread (listening on the socket and "handling some other events"), do that in different threads. 3. If you do need a timeout (not for multiplexing, but for a genuine timeout), use System.Timeout.
Roman _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
-- Alberto.
-- Alberto.

On 11/09/2014 08:11 AM, Roman Cheplyaka wrote:
Let's say you knew what exceptions could be thrown. What would you do differently then?
Typically, if it's a command-line app and something unexpected happens, you simply present the error to the user. That's what exceptions do already without any effort from you.
The output from the exception is usually useless, though. Rather than, *** Exception: EACCES (or something similar, whatever, I'm making it up), I want to show: Insufficient permissions for accessing /run/<app>. This can be fixed by granting write and execute access on that directory to the user under which the application is running. If the operation can fail in different ways -- like if the directory is missing entirely -- I need to pattern match on the exception and display something else. Another example: I don't want to log a "read error" in my daemon, which is what I'll get if I log the exception. I want to know *what* failed to be read. Was it a file (that a cron job deleted) or a network socket (whose connection was dropped)? I need to catch those in the code, where I know what's being read, and what the "read error" means in context.

On 09/11/14 08:38, Michael Orlitzky wrote:
On 11/09/2014 08:11 AM, Roman Cheplyaka wrote:
Let's say you knew what exceptions could be thrown. What would you do differently then?
Typically, if it's a command-line app and something unexpected happens, you simply present the error to the user. That's what exceptions do already without any effort from you.
The output from the exception is usually useless, though. Rather than,
*** Exception: EACCES
(or something similar, whatever, I'm making it up), I want to show:
Insufficient permissions for accessing /run/<app>. This can be fixed by granting write and execute access on that directory to the user under which the application is running.
If the operation can fail in different ways -- like if the directory is missing entirely -- I need to pattern match on the exception and display something else.
Another example: I don't want to log a "read error" in my daemon, which is what I'll get if I log the exception. I want to know *what* failed to be read. Was it a file (that a cron job deleted) or a network socket (whose connection was dropped)? I need to catch those in the code, where I know what's being read, and what the "read error" means in context.
Both points are valid. Re the first, you still can achieve it by pattern-matching on exceptions. The fact that you don't know the exact set of exceptions makes it harder, but the truth is, for a non-trivial application, that set would be huge. Like, let's say you use a database. It brings in all sorts of network-related exceptions and database-level exceptions. The way to handle those, as you point out, is to augment them with high-level information ("Could not retrieve user's data"), and then maybe attach the low-level exception for debugging purposes. Again, you don't really need to know the whole set of exceptions in order to do that. Just wrap your database access function in 'try', and you'll know that whatever exception was caught, it prevented the retrieval of user's data (but keep in mind that it might be an asynchronous exception unrelated to your database activity). Roman

Whether thrown exceptions should be explicitly part of interface or not is
still an open issue. For example, Java requires to explicitly declare the
exception as part of method signature. And people complained... Then in
Scala, for example, there's no such requirement. I've seen a paper showing
negative consequences of implicit exceptions but I cannot find it now (I
thought it was ICSE 2014...).
I found some other paper contrasting implicit vs. explicit exception flows.
http://www.les.inf.puc-rio.br/opus/docs/pubs/2009/10_NelioCacho-SBES2009.pdf
So, sometimes you need to handle the exception at the call site but if it's
required that people simply "swallow" the exception (catch and do nothing),
sometimes you need to handle them centrally in some way. I'm not sure what
is best for Haskell.
Michal
On Sun, Nov 9, 2014 at 8:53 AM, Roman Cheplyaka
On 09/11/14 08:38, Michael Orlitzky wrote:
On 11/09/2014 08:11 AM, Roman Cheplyaka wrote:
Let's say you knew what exceptions could be thrown. What would you do differently then?
Typically, if it's a command-line app and something unexpected happens, you simply present the error to the user. That's what exceptions do already without any effort from you.
The output from the exception is usually useless, though. Rather than,
*** Exception: EACCES
(or something similar, whatever, I'm making it up), I want to show:
Insufficient permissions for accessing /run/<app>. This can be fixed by granting write and execute access on that directory to the user under which the application is running.
If the operation can fail in different ways -- like if the directory is missing entirely -- I need to pattern match on the exception and display something else.
Another example: I don't want to log a "read error" in my daemon, which is what I'll get if I log the exception. I want to know *what* failed to be read. Was it a file (that a cron job deleted) or a network socket (whose connection was dropped)? I need to catch those in the code, where I know what's being read, and what the "read error" means in context.
Both points are valid.
Re the first, you still can achieve it by pattern-matching on exceptions. The fact that you don't know the exact set of exceptions makes it harder, but the truth is, for a non-trivial application, that set would be huge. Like, let's say you use a database. It brings in all sorts of network-related exceptions and database-level exceptions.
The way to handle those, as you point out, is to augment them with high-level information ("Could not retrieve user's data"), and then maybe attach the low-level exception for debugging purposes. Again, you don't really need to know the whole set of exceptions in order to do that. Just wrap your database access function in 'try', and you'll know that whatever exception was caught, it prevented the retrieval of user's data (but keep in mind that it might be an asynchronous exception unrelated to your database activity).
Roman _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

There's also the `ExceptT` monad transformer, which effectively binds
exceptions to a type:
http://hackage.haskell.org/package/mtl-2.2.1/docs/Control-Monad-Except.html
It is not restrictive in any way, though, ie. there still can be other
excpetions raised in your application unless you account for them, but
otherwise it does a decent job at managing exceptions…
On Sun, Nov 9, 2014 at 4:01 PM, Michal Antkiewicz wrote: Whether thrown exceptions should be explicitly part of interface or not is
still an open issue. For example, Java requires to explicitly declare the
exception as part of method signature. And people complained... Then in
Scala, for example, there's no such requirement. I've seen a paper showing
negative consequences of implicit exceptions but I cannot find it now (I
thought it was ICSE 2014...). I found some other paper contrasting implicit vs. explicit exception flows. http://www.les.inf.puc-rio.br/opus/docs/pubs/2009/10_NelioCacho-SBES2009.pdf So, sometimes you need to handle the exception at the call site but if
it's required that people simply "swallow" the exception (catch and do
nothing), sometimes you need to handle them centrally in some way. I'm not
sure what is best for Haskell. Michal On Sun, Nov 9, 2014 at 8:53 AM, Roman Cheplyaka On 09/11/14 08:38, Michael Orlitzky wrote: On 11/09/2014 08:11 AM, Roman Cheplyaka wrote: Let's say you knew what exceptions could be thrown. What would you do
differently then? Typically, if it's a command-line app and something unexpected happens,
you simply present the error to the user. That's what exceptions do
already without any effort from you. The output from the exception is usually useless, though. Rather than, *** Exception: EACCES (or something similar, whatever, I'm making it up), I want to show: Insufficient permissions for accessing /run/<app>. This can be fixed
by granting write and execute access on that directory to the user
under which the application is running. If the operation can fail in different ways -- like if the directory is
missing entirely -- I need to pattern match on the exception and display
something else. Another example: I don't want to log a "read error" in my daemon, which
is what I'll get if I log the exception. I want to know *what* failed to
be read. Was it a file (that a cron job deleted) or a network socket
(whose connection was dropped)? I need to catch those in the code, where
I know what's being read, and what the "read error" means in context. Both points are valid. Re the first, you still can achieve it by pattern-matching on
exceptions. The fact that you don't know the exact set of exceptions
makes it harder, but the truth is, for a non-trivial application, that
set would be huge. Like, let's say you use a database. It brings in all
sorts of network-related exceptions and database-level exceptions. The way to handle those, as you point out, is to augment them with
high-level information ("Could not retrieve user's data"), and then
maybe attach the low-level exception for debugging purposes. Again, you
don't really need to know the whole set of exceptions in order to do
that. Just wrap your database access function in 'try', and you'll know
that whatever exception was caught, it prevented the retrieval of user's
data (but keep in mind that it might be an asynchronous exception
unrelated to your database activity). Roman
_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe _______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe
participants (7)
-
Alberto G. Corona
-
Michael Orlitzky
-
Michal Antkiewicz
-
Nils Schweinsberg
-
Roman Cheplyaka
-
Tom Ellis
-
Ömer Sinan Ağacan