2016-12-13 4 views

ответ

2

Это не относится к HUnit, но вы можете написать функцию для проверки кидает ли IO значение:

λ> :set -XScopedTypeVariables 
λ> import Control.Exception 
λ> import Data.Functor 
λ> import System.Environment 

λ> throws io = catch (io $> False) $ \(e :: SomeException) -> pure True 
throws :: IO a -> IO Bool 

λ> sequence $ throws <$> [ getEnv "HOME", getEnv "whatever", error "a" ] 
[False,True,True] 
+0

Будет ли это работать и для «ошибки»? – cberkay

+0

Да, если вы используете 'error' для создания значений типа' IO'. Я обновил ответ, чтобы включить это. –

+0

Спасибо. Я, вероятно, отсутствует что-то очевидное, но когда я ввожу свой код в repl, я получаю сообщение об ошибке для 'throws io = ...': 'Недопустимая подпись типа: 'SomeException' Подписи типов допускаются только в шаблонах с ScopedTypeVariables' – cberkay

2

Если с помощью «исключение» вы имеете в виду Exception и его бросают в некоторых IO код, то вы можете использовать . Однако, если вы имеете в виду ловить вещи вроде error "Something bad happened"в чистом коде, вам не повезло. Если вы готовы сделать обработку в IO, у вас есть больше возможностей:

ghci> import Control.Exception 
ghci> catch (error "Eek") (\(ErrorCallWithLocation msg _) -> putStrLn msg) 
Eek 

Из отчета о Haskell 2010 section 3:

Ошибки во время вычисления выражений, обозначаемые ⊥ («дно »), Неотличимы от программы Haskell от неограниченного доступа.

Вот еще один способ думать об этом: обратите внимание, что в тот момент мы пытаемся оценить значение, которое ⊥ (как error "Help!") зависит не от того, когда это значение было создано но только тогда, когда он был первым нужен (поскольку Haskell не является строгим). Механизм, чтобы поймать такую ​​ошибку, затем нарушит ссылочную прозрачность.

+0

Я вижу. К сожалению, мне это понадобилось для случая с «ошибкой». – cberkay

+0

@cberkay Добавлено. До тех пор, пока вы захотите поймать внутри монады IO, это возможно. – Alec

Смежные вопросы