В чем разница между throw и throwIO - PullRequest
0 голосов
/ 02 января 2019

Документация гласит:

Вариант throwIO следует использовать предпочтительнее для выброса, чтобы вызвать исключение в монаде IO, поскольку оно гарантирует упорядочение относительно других операций IOтогда как throw не.

Я все еще растерялся после прочтения.Есть ли пример, чтобы показать, что throw вызовет проблему, а throwIO не будет?

Дополнительный вопрос:

Правильно ли следующее утверждение?

  1. Если throw используется для выброса исключения в IO, тогда порядок исключения не гарантируется.
  2. Если throw используется для выброса исключения в значении не-IO, то порядокисключение гарантируется.

Если мне нужно выдать исключение в Monad Transformer, которое я должен использовать throw вместо throwIO, гарантирует ли это порядок исключения?

Ответы [ 2 ]

0 голосов
/ 02 января 2019

throw является обобщением undefined, в то время как throwIO является действительным IO действием.Ключевое отличие состоит в том, что многие законы не совсем соблюдаются, когда рассматривается строгость (т. Е. Когда у вас есть undefined (или throw) и seq).

> (throw Underflow :: IO ()) `seq` ()
*** Exception: arithmetic underflow
> (throw Underflow >>= pure) `seq` ()
()

Следовательно, противоречащие законуm >>= pure = mthrowIO такой проблемы нет, поэтому это более принципиальный способ создания исключений.

0 голосов
/ 02 января 2019

Я думаю, что документы могут быть улучшены.Проблема, которую вы должны учитывать при throw и т. П., Заключается в том, что throw возвращает нижнее значение, которое «взрывается» (вызывает исключение) при оценке;но то, когда и когда происходит оценка, трудно контролировать из-за лени.

Например:

Prelude Control.Exception> let f n = if odd n then throw Underflow else True
Prelude Control.Exception> snd (f 1, putStrLn "this is fine")
this is fine

Возможно, это то, что вы хотите, но обычно нет.например, вместо приведенного выше кортежа вы можете получить большую структуру данных с одним взрывающимся элементом, который вызывает исключение, которое будет вызвано после того, как ваш веб-сервер вернет пользователю 200, или что-то в этом роде.

throwIO позволяетВы можете последовательно вызывать исключение, как если бы это было другое действие ввода-вывода, поэтому его можно жестко контролировать:

Prelude Control.Exception> throwIO Underflow >> putStrLn "this is fine"
*** Exception: arithmetic underflow

... точно так же, как и print 1 >> print 2.

Но обратите внимание, чтона самом деле вы можете заменить throwIO на throw, например:

Prelude Control.Exception> throw Underflow >> putStrLn "this is fine"
*** Exception: arithmetic underflow

Так как теперь значение взрыва имеет тип IO a.На самом деле мне не понятно, почему существует throwIO, кроме как документировать идиомуМожет быть, кто-то еще может ответить на этот вопрос.

В качестве последнего примера, это та же проблема, что и мой первый пример:

Prelude Control.Exception> return (throw Underflow) >> putStrLn "this is fine"
this is fine
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...