
The IOError type re-exported from GHC.IO.Exception by System.IO.Error has accessors for some of the error elements fields, but is notably missing an accessor for ioe_description, which is only available as "ioeGetErrorString" for UserError, for all other errors you just get the string form of the error type: ioeGetErrorType :: IOError -> IOErrorType ioeGetErrorString :: IOError -> String ioeGetLocation :: IOError -> String ioeGetHandle :: IOError -> Maybe Handle ioeGetFileName :: IOError -> Maybe FilePath ioeGetErrorString ioe | isUserErrorType (ioe_type ioe) = ioe_description ioe | otherwise = show (ioe_type ioe) the real ioe_description for other error types can only be brought into scope by importing GHC.IO.Exception instead, or alternatively via the System.IO.Error.Lens: -- | Error type specific information. description :: Lens' IOException String description f s = f (ioe_description s) <&> \e -> s { ioe_description = e } {-# INLINE description #-} I am curious why ioeGetDescription was left out of System.IO.Error, and/or why it should not be added? Somehow it feels "wrong" to import GHC.IO.Exception instead of System.IO.Error just to get at the specific error text... Is it the case that, given all the other language extensions my code depends on, I should not have any qualms about importing GHC.* modules? Or perhaps is it the case that one should just start using lens, and so adding "missing" record accessors just delays migration to the right way and is no longer a priority? -- Viktor.