Как правильно обрабатывать все возможные ошибки при использовании канала HTTP?

У меня есть код, который выглядит так:

retryOnTimeout :: IO a -> IO a
retryOnTimeout action = catch action $ \ResponseTimeout -> 
                            do putStrLn "Timed out. Trying again."
                               threadDelay 5000000
                               action 

Проблема в том, что существует множество других конструкторов HttpException, и я хотел бы, как правило, продолжать попытки снова, независимо от того, в чем именно заключается ошибка. Теперь, если я заменю ResponseTimeout на _, я получу ошибку компиляции, потому что он не может определить тип исключения.

Я действительно не хочу предоставлять сигнатуру типа для обработчика исключений.

Я знаю, что это не большое дублирование, но добавление случая для _ кажется неправильным, потому что это все равно, что сказать: если исключение — ResponseTimeout, то сделайте x, но если исключение — что-то еще, сделайте точно то же самое вещь. Есть ли краткий способ использовать подстановочный знак, но при этом сообщить компилятору, какой это тип?


person Peter Hall    schedule 10.08.2013    source источник
comment
Как насчет catch action $ \ (_ :: HttpException) -> do ...? Возможно, для компиляции необходимо включить ScopedTypeVariables.   -  person Nathan Howell    schedule 10.08.2013
comment
Ааааа! ScopedTypeVariables! GHC даже предложил это, но я подумал, что это ошибочно, потому что я никогда раньше не видел именно такого использования расширения. Пожалуйста, добавьте в качестве ответа, чтобы я мог принять, спасибо!   -  person Peter Hall    schedule 10.08.2013
comment
Вы также можете написать \~ResponseTimeout -> , который связывает тип без фактического сопоставления, поскольку ~ — это ленивый шаблон. Однако ScopedTypeVariables — гораздо лучшее решение.   -  person Neil Mitchell    schedule 13.08.2013


Ответы (1)


Если вас не волнует значение исключения, вполне нормально использовать _, но вам нужно будет использовать ScopedTypeVariables или предложение let, чтобы указать нужный тип.

{-# LANGUAGE ScopedTypeVariables #-}

retryOnTimeout :: IO a -> IO a
retryOnTimeout action = catch action $ \ (_ :: HttpException) -> do
  putStrLn "Timed out. Trying again."
  threadDelay 5000000
  action
person Nathan Howell    schedule 10.08.2013