【问题标题】:How to handle exception within a servant handler monad?如何在仆人处理程序 monad 中处理异常?
【发布时间】:2019-06-21 19:26:05
【问题描述】:

我想在仆人处理程序 monad 中处理数据库异常。

我尝试使用 Control.Exception 包中的 try 函数来与 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))
   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

【问题讨论】:

  • 我不确定,但我认为liftIO 将您的IO Account 结果提升到Handler monad。如果是这样,也许try 应该先走,liftIO 第二:result &lt;- liftIO (try (insertAccount payload))
  • @MarkSeemann 将案例中的模式匹配更新为Left (PGError e) -&gt; 就成功了。谢谢!如果您发布该答案,我会接受。

标签: haskell servant


【解决方案1】:

我认为liftIO 将您的IO Account 结果提升到Handler monad。如果是这样,也许try 应该先走,liftIO 第二:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-04
    相关资源
    最近更新 更多