如何在仆人处理程序monad中处理异常?

时间:2019-06-21 19:26:05

标签: haskell servant

我想在服务方处理程序monad中处理数据库异常。

我尝试使用try包中的Control.Exception函数,以便能够与Left exception -> throwError err422 { errBody = ... }进行大小写匹配。

我正在使用postgresql-typed与PostgreSQL数据库进行交互。我想捕获一个PGError异常。

relevant code经过以下修改:

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 个答案:

答案 0 :(得分:2)

我认为liftIO将您的IO Account结果提升到Handler单子。如果是这样,也许try应该先行,liftIO其次:

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