Я пытаюсь лучше понять, как обрабатывать состояния ошибок в Haskell, поскольку кажется, что есть много способов сделать это.В идеале мои структуры данных сделали бы любые недопустимые входные данные непредставимыми, но, несмотря на значительные усилия, наоборот, я все равно иногда заканчиваю работать с данными, где система типов может допускать недопустимые состояния.В качестве примера, давайте рассмотрим, что мой программный ввод - это результаты обучения нейронной сети.Чтобы математика работала, каждая матрица должна иметь правильные границы, а это (на самом деле) не представляется системой типов.Если данные недействительны, приложение на самом деле ничего не может сделать, кроме как прекратить дальнейшую обработку и уведомить кого-либо о проблеме (поэтому она не подлежит восстановлению).Какой лучший способ справиться с этим в Haskell?Кажется, я мог бы:
1) Использовать error
или другие частичные функции при обработке моих данных.Насколько я понимаю, это следует использовать только для представления ошибки в коде.Так что это должно быть связано с некоторой проверкой в момент, когда я загружаю данные, и в любой точке «после» этой проверки я просто предполагаю, что данные находятся в допустимом формате.Это крайне необходимо для меня, и, похоже, не очень подходит для ленивого декларативного кода.
2) Создайте исключение при обработке данных с использованием Control.Exception.throw
, а затем перехватите его на верхнем уровне, гдеЯ могу предупредить кого-то.Вопреки error
, я считаю, что это не указывает на ошибку в программе, поэтому, возможно, не будет проверки, когда я загружу данные за пределы того, что может быть представлено через систему типов?Наличие или отсутствие исключения при обработке данных определит проверку.
3) Поднимите любую обработку данных, которая может не сработать, в монаду ввода-вывода и используйте Control.Exception.throwIO
.
4) Поднимителюбая обработка данных, которая может привести к сбою в монаде ввода-вывода и использовать fail
(я читал, что использование fail
не одобрено сообществом?)
5) Вернуть Either
или что-то подобное, ипозвольте этому пузыриться через всю вашу логику.У меня определенно были некоторые случаи, когда составление Either
с становится (для меня) чрезвычайно непрактичным.
6) Используйте Control.Monad.Exception, который я только немного понимаю, но, кажется, включает в себя отмену любой обработки данныхэто может привести к какой-то исключительной монаде, которую, я думаю, легче составить, чем Either
?
, и я даже не уверен, что это все варианты.Есть ли подход к этой проблеме, общепринятый сообществом, или это действительно продуманная тема?