Отображение из исключения в ExceptT - PullRequest
1 голос
/ 16 апреля 2020

Я читаю главу об исключениях, поэтому я решил поэкспериментировать и сопоставить исключение с преобразователем монад ExceptT. Моя функция getInt может читать целое число из консоли и сообщать об исключениях в виде Left "что не так":

getInt :: ExceptT String IO Int
getInt = ExceptT $ do
    Right . read <$> getLine
    `catch` \(e :: ErrorCall) -> return . Left . show $ e

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

getInt :: ExceptT String IO Int
getInt = ExceptT $ do
    read <$> getLine >>= seq <*> return . Right
    `catch` \(e :: ErrorCall) -> return . Left . show $ e

Результат: Слева "Prelude.read: no parse". Теперь это работает!

Мой вопрос здесь - это правильный путь, как сопоставить исключение с ExceptT?

1 Ответ

2 голосов
/ 16 апреля 2020

Правильный способ действительно состоит в том, чтобы форсировать оценку read. Это можно сделать более элегантно с помощью приложения «вызов по значению» $!

getInt :: ExceptT SomeException IO Int
getInt = ExceptT $ liftIO $ try @SomeException $ do
  i <- getLine
  pure $! read i

Обычно лучше параметризовать базовую монаду (из соображений тестируемости и возможности повторного использования), поэтому мы могли бы написать

getInt :: (MonadError SomeException m, MonadIO m) => m Int
getInt = liftEither =<< liftIO $ try @SomeException $ do
  i <- getLine
  pure $! read i

Мертвый бетонный монадный трансформаторный стек ExceptT SomeException IO Int

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...