Ещё об обработке ошибок в Rust

Aug 24, 2015 22:46

С обработкой ошибок в Rust надо явно что-то придумывать. Мне категорически нравится, что в языке нет исключений, но без синтаксического сахара вроде хаскелевской конструкции do код с аккуратной обработкой ошибок визуально превращается в простыню с перекладыванием значений из одних типов в другие ( Read more... )

exceptions, code, rust, errors, error handling, language

Leave a comment

thesz August 25 2015, 09:43:29 UTC
Твоя иерархия успехов это комбинация монад Maybe и Either (успех/неуспех и успех/конкретная ошибка). При этом монадичность оных не используется - если у тебя нет использования >>=, или ты можешь переписать всё на >>, то это аппликативный функтор.

Поэтому всё более-менее просто, даже do не надо. Разбор строки даёт Either (parse :: String -> Either String a), наличие/отсутствие параметра Maybe. Поэтому разбор комбинируется просто: fmap parseVec64f как раз будет иметь тип Maybe String -> Maybe (Either String Vec64f).

Reply

swizard August 25 2015, 13:45:59 UTC
Согласен насчёт аппликативных функторов. Ответил в другой ветке про это.

Reply

swizard August 25 2015, 13:51:58 UTC
> fmap parseVec64f как раз будет иметь тип Maybe String -> Maybe (Either String Vec64f).

Кстати, вот ты сходу предлагаешь все возможные ошибки унифицировать в тип String - если я правильно понимаю, это просто сообщение об ошибке.

А как быть, если внутри parseVec64f используется функция parse64f, тип ошибки у которой другой - например, перечисление вроде InvalidSymbol Char | Overflow | EmptyString. И, например, используется какая-то другая функция с другим типом ошибки.

Как это всё аккуратно принести наружу из parseVec64f? Например, мне в логике выше нужно делать разные действия, в зависимости от разных типов ошибок?

Reply

thesz August 25 2015, 14:24:42 UTC
В принципе, Either a b вполне себе обобщается до нужных результатов и ошибок.

Выражение fmap parse не изменится, если ты изменишь тип ошибки.

Reply

swizard August 25 2015, 14:52:17 UTC
Но в "Either a b" фиксированный тип "a", получается, что все функции, использующиеся внутри parseVec64f должны возвращать ошибку одного и того же типа.

Но что если это не так?

Reply

thesz August 25 2015, 15:09:17 UTC
Прошу привести пример, где это не так, это раз.

fmap для Either имеет тип (a -> b) -> Either e a -> Either e b. Для преобразования ошибок мы можем сделать комбинатор mapErr :: (e -> s) -> Either e a -> Either s a.

Тогда для преобразования ошибок мы можем использовать mapErr :: fmap (mapErr simplifyError . parse).

Это два.

Reply

swizard August 25 2015, 15:16:47 UTC
А, ну понятно теперь.

Собственно, в Rust ровно так и сделано (Either = Result, mapErr = map_err), я просто думал, в хаскеле ещё какой-то механизм есть.

Reply

thesz August 25 2015, 15:20:37 UTC
Ну, что, как типизированное программирование? Общие впечатления, там, всё такое. ;)

Reply

swizard August 25 2015, 15:39:49 UTC
Да так же, по-большому счёту :) Но сопоставление с образцом заметно удобней работает, конечно.

Но я ж не первый раз с типами встречаюсь, я на хаскеле уже успел попрограммировать. Даже в конкурсе каком-то недавно на нём участвовал =)

Reply


Leave a comment

Up