From: Axel S. <A....@ke...> - 2004-07-14 09:35:02
|
On Tue, Jul 13, 2004 at 01:51:04PM +0100, Duncan Coutts wrote: > > I think this is ok because the most common case is that you want to handle > > the errors of exacly one domain. > > Right, that would definitely be the common case. What I was hoping was > that it would auto-magically convert to the right enum for the domain I > was interested in handling. > > Something like: > handleGErrorJustDomain :: > GErrorDomain errorEnum => > IO a -> > (errorEnum -> ErrorMessage -> IO a) -> > IO a > > So the handler only deals with one error domain enum. From that, the > handler function figures out which error domain code to look for. I think that's fine. > > That would suggest a type class scheme like so: > > class Enum err => GErrorDomain err where > gerrorDomain :: err -> GErrorDomainCode > > instance GErrorDomain GdkPixbufLoaderError where > gerrorDomain _ = unsafePerformIO {#call unsafe pixbuf_error_quark#} > > handleGErrorJustDomain would be implemented something like: > > catchGErrorJustDomain action (handler :: err -> String -> IO a) = catchGError action handler' > where handler' gerror@(GError domain code msg) > | domain == gerrorDomain (undefined::err) = handler (toEnum code) msg > | otherwise = throwGError gerror Nice. But I guess you have to document this with an example. It might be confusing that you need two catch statements if you are catching errors from different domains. But maybe that really never happens. > > Yes, perhaps that works. If GError had a fake type parameter which > > is GdkPixbufLoaderError for the specific class, does that work with the > > dynamic types? > > You mean like: > > data GError dom = GError GErrorDomainCode GErrorCode String > > So you can have GError GdkPixbufLoaderError. Of course then the > GErrorDomainCode does not need to be stored in the GError since it can > be found from the type parameter. I'm not sure about dynamic types like > this, it just needs a quick experiment. I'd be happy with the other methods. It seems sufficiently simple and easy to use in practice. Your choice. > > > > At the moment people just call initGUI & mainGUI which are not suitable > > > for installing error handlers because they return rather than taking a > > > continuation. > > > > So true. > > Perhaps we should add such a function > runGUI :: IO a -> IO a > runGUI main = do > initGUI > catchGError main > (\GError -> ...) > mainGUI > > On the other hand initialisation gets more complicated (requires more > parameters) once we add other gnome libs into the mix. We might want to > hold off creating new initialisation APIs until the requirements become > clearer. I don't have a strong opinion about this. > > There is a silent exception handler wrapped around each callback, hence > > GHC will abort the program if an exception occurs in a callback. But since > > we are generating all the signal handlers automatically, we could add our > > own 'catch' statement that calls an exception handler in some global > > variable. I suppose there aren't that many possibilities of raising > > GErrors in the main program, are they? In that case, a global error > > handler might be the cleanest thing. The only problem is that it is not > > clear how to determine the return value after an exception has been raised > > within a callback. > > It might be sufficient to simply terminate the program with a helpful > error message. At least that gives people the chance of handling the > error if they want to or in a throwaway program to at least get some > diagnostic. Then we can avoid the issue of returning something in the > case that an error was thrown. Afterall, ghc just terminates the program > in the case of an unhandled exception, abeit only at the top level > rather than in each signal handler as we'd do. We could wrap each signal handler in a catch-clause that converts GErrors to UserErrors which are more legible to the user. > While looking at that, I'd suggest looking at whether it'd be better to > keep package.conf files in each directory that builds into a package > rather than generating them from the makefile. It'd allow easier > per-package modifications, also I found when packaging a number of libs > for Gentoo that using actual .conf files made modifying the install > location rather easier. ghc's ghc-pkg allows some template mechanisms > that it expands when the .conf file is merged into the global > pacage.conf file. Yes, I can see that it might make things easier. There were some dodgy things about substiting a variable with several paths, though. > BTW I remember some extra effort needed in the makefiles to strip out > directories that don't exist from the package.conf files because > otherwise ghc-pkg would complain. I just noticed that there is a --force > option that will make ghc-pkg not check for non-existent directories. The -f flag didn't exist in ghc 5.XX. So I suppose I can remove the test. Axel. |