Ответ 1
Не слишком долго после выхода RWH интерфейс исключений был изменен для поддержки более гибких обработчиков, где тип обработчика определяет, какие исключения он будет ловить. Например. обработчик, который принимает SomeException
, поймает что-нибудь (обычно это не очень хорошая идея), в то время как обработчик, который принимает IOException
, будет захватывать только исключения IO.
В результате этого легко столкнуться с проблемами двусмысленности с обработчиками do-nothing, такими как в вашем примере, поскольку компилятор не может определить, какие исключения вы пытаетесь поймать. Легкий способ исправить это - предоставить сигнатуру типа для вашей функции обработчика.
handle ((\_ -> return Nothing) :: IOException -> IO (Maybe Integer)) $ do ...
Хотя, это может быть несколько многословным. Альтернативным решением является специализация handle
.
handleIO :: (IOException -> IO a) -> IO a -> IO a
handleIO = handle
Затем вы можете просто использовать handleIO
всякий раз, когда хотите обрабатывать исключения IO, без необходимости указывать подпись типа обработчика.
saferFileSize path = handleIO (\_ -> return Nothing) $ do ...
Третий вариант - использовать расширение ScopedTypeVariables
, которое (среди прочего) позволяет вам предоставлять аннотацию типа только для аргумента функции, позволяя остальным быть выведенным.
{-# LANGUAGE ScopedTypeVariables #-}
saferFileSize path = handle (\(_ :: IOException) -> return Nothing) $ do ...