我正在使用 Scotty 和 Persistent 开发 REST 后端,但我无法找出处理错误的正确方法。
我有几个函数可以访问数据库,例如:
getItem :: Text -> SqlPersistM (Either Error Item)
它在 sql monad 内部返回。然后我在我的操作中使用它来检索项目并返回它的 JSON 表示:
get "/items/:name" $ do
name <- param "name"
eitherItem <- lift $ MyDB.getItem name
case eitherItem of
Left NotFound -> do
status status404
json NotFound
Left InvalidArgument -> do
status status400
json BadRequest
Right item -> json item
我可以通过引入一些帮助程序使代码更漂亮,但模式将保持不变——访问数据库、检查错误、呈现适当的响应。
我想完全摆脱我的操作中的错误处理:
get "/items/:name" $ do
name <- param "name"
item <- lift $ MyDB.getItem name
-- In case of error, appropriate
-- HTTP response will be sent,
-- else just continue
bars <- lift $ MyDB.listBars
-- In case of error, appropriate
-- HTTP response will be sent,
-- else just continue
json (process item bars)
即getItem
可能返回错误,它会以某种方式转换为 json 响应,对操作代码都是透明的。getItem
如果对动作和 json 响应一无所知,那就太好了。
我过去使用命令式语言解决了这个问题,方法是从各处抛出异常,然后将其捕获到一个地方并呈现适当的响应。我想 Haskell 也可以,但我想知道如何通过使用功能工具来解决这个问题。
I know it is possible for monads to short-circuit (like Either >> Either >> Either
) but have no idea how to use it in this slightly more complicated case.