С обработкой ошибок в Rust надо явно что-то придумывать. Мне категорически нравится, что в языке нет исключений, но без синтаксического сахара вроде хаскелевской конструкции do код с аккуратной обработкой ошибок визуально превращается в простыню с перекладыванием значений из одних типов в другие
(
Read more... )
Поэтому всё более-менее просто, даже do не надо. Разбор строки даёт Either (parse :: String -> Either String a), наличие/отсутствие параметра Maybe. Поэтому разбор комбинируется просто: fmap parseVec64f как раз будет иметь тип Maybe String -> Maybe (Either String Vec64f).
Reply
Reply
Кстати, вот ты сходу предлагаешь все возможные ошибки унифицировать в тип String - если я правильно понимаю, это просто сообщение об ошибке.
А как быть, если внутри parseVec64f используется функция parse64f, тип ошибки у которой другой - например, перечисление вроде InvalidSymbol Char | Overflow | EmptyString. И, например, используется какая-то другая функция с другим типом ошибки.
Как это всё аккуратно принести наружу из parseVec64f? Например, мне в логике выше нужно делать разные действия, в зависимости от разных типов ошибок?
Reply
Выражение fmap parse не изменится, если ты изменишь тип ошибки.
Reply
Но что если это не так?
Reply
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
Собственно, в Rust ровно так и сделано (Either = Result, mapErr = map_err), я просто думал, в хаскеле ещё какой-то механизм есть.
Reply
Reply
Но я ж не первый раз с типами встречаюсь, я на хаскеле уже успел попрограммировать. Даже в конкурсе каком-то недавно на нём участвовал =)
Reply
Leave a comment