Как обрабатывать исключения в монаде обработчик слуг? - PullRequest
4 голосов
/ 21 июня 2019

Я хочу обработать исключение базы данных внутри монады обработчика слуги.

Я пытался использовать функцию try из пакета Control.Exception, чтобы иметь возможность совпадать с Left exception -> throwError err422 { errBody = ... }.

Я использую postgresql-type для взаимодействия с базой данных PostgreSQL. Я хочу получить исключение PGError .

Код , соответствующий со следующей модификацией:

accountHandler :: CreateAccountPayload -> Handler Account
accountHandler payload =
  let errors = validateCreateAccountPayload payload in
  if hasErrors errors then
    throwError err422 { errBody = JSON.encode errors }
  else
    do
      result <- try (liftIO (insertAccount payload))
      case result of
        Right account -> return account
        Left exception -> throwError err422 { errBody = JSON.encode [ValidationError (Text.pack "email") (Text.pack "is already taken")] }

Я ожидаю, что смогу получить результат от вызова базы данных и сопоставить его с регистром. Случаи должны быть для исключения или значения. В настоящее время я получаю следующую ошибку компиляции:

src/Main.hs:64:17: error:
    • Couldn't match type ‘IO’ with ‘Handler’
      Expected type: Handler (Either e0 Account)
        Actual type: IO (Either e0 Account)
    • In a stmt of a 'do' block:
        result <- try (liftIO (insertAccount payload))
      In the expression:
        do result <- try (liftIO (insertAccount payload))
           case result of
             Right account -> return account
             Left exception -> throwError err422 {errBody = encode ...}
      In the expression:
        if hasErrors errors then
            throwError err422 {errBody = encode errors}
        else
            do result <- try (liftIO (insertAccount payload))
               case result of
                 Right account -> return account
                 Left exception -> throwError ...
   |
64 |       result <- try (liftIO (insertAccount payload))
   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

1 Ответ

2 голосов
/ 22 июня 2019

Я думаю, что liftIO поднимает ваш IO Account результат в монаду Handler. Если это так, возможно, try должен идти первым, а liftIO вторым:

result <- liftIO (try (insertAccount payload))
case result of
    Right account -> return account
    Left (PGError e) -> throwError err422
...