bet*_*eta 6 haskell monad-transformers servant
仆人服务器处理程序是 , 的新类型包装器ExceptT,并且具有MonadThrow, MonadCatch,MonadError等的实例。
这可能是一个有点人为的例子,但它显示了我经常面临的一个问题:
\n\n在处理程序中,我想调用三个返回的函数Either String Int,然后执行类型的计算,获取之前的Int -> Int -> Int -> IO (Either SomeError Text)三个s 。Int
我应该如何构造这段代码以确保尽早返回错误?
\n\n我看到我可以使用Either\'sMonad实例将 \xe2\x80\x9ccollapse\xe2\x80\x9d 的前三个Either String Int计算放入 eg 中Either String (Int,Int,Int),然后将IO计算绑定到某个结果值,然后用于case决定是否返回成功结果或用于throwError抛出SomeError类型(转换后?),但我希望能够执行以下操作:
f, g, h :: Either String Int\na :: Int -> Int -> Int -> IO (Either SomeError Text) \n\nmyHandler :: Handler Text\nmyHandler = do\n x1 <- f\n x2 <- g\n x3 <- h\n liftIO $ convertError $ (a x1 x2 x3)\nRun Code Online (Sandbox Code Playgroud)\n\n是否可以像上面的代码那样写?
\n假设您有一个函数strToServantErr :: String -> ServantErr可以将返回的错误转换f,g,h为处理程序可以返回的错误,那么我们可以使用:
liftEither将Either String Ints 变成ExceptT Strings。withExceptT根据 的要求从 转换ExceptT String为。ExceptT ServantErrHandlerx1 <- withExceptT strToServantErr $ liftEither f
Run Code Online (Sandbox Code Playgroud)
当您执行此操作三次时,我们可以使用以下命令使其更简洁mapM:
[x1, x2, x3] <- mapM (withExceptT strToServantErr . liftEither) [f, g, h]
Run Code Online (Sandbox Code Playgroud)
现在我们已经对参数进行了排序,我们可以使用相同的想法来修复返回。将您的convertError函数重命名为以someErrorToServantErr保持一致性并假设它具有 type SomeError -> ServantErr,那么我们可以这样做:
result <- liftIO $ a x1 x2 x3
withExceptT someErrorToServantErr $ liftEither result
Run Code Online (Sandbox Code Playgroud)
我们解开IO的计算a,然后将其提升为ExceptT并转换异常类型。
将一些代码整理到辅助函数中后,我们得到如下内容:
myHandler :: Handler Text
myHandler = do
[x1, x2, x3] <- mapM (liftMapE strToServantErr) [f, g, h]
eitherResult <- liftIO $ a x1 x2 x3
liftMapE someErrorToServantErr eitherResult
where liftMapE f = withExceptT f . liftEither
Run Code Online (Sandbox Code Playgroud)
这将尽快失败,并根据需要转换错误,虽然它很密集,但希望不是那么不可读。
你也可以走Applicative路线,尽管我找不到一种让它特别好的方法(虽然我没有太多使用applicative函子,但我可能错过了一些有用的技巧):
myHandler :: Handler Text
myHandler = do
let [x1, x2, x3] = map (liftMapE strToServantErr) [f, g, h] -- [Handler Int]
tmp <- a <$> x1 <*> x2 <*> x3 -- IO (Either SomeError Text)
eitherResult <- liftIO $ tmp
liftMapE someErrorToServantErr eitherResult
where liftMapE f = withExceptT f . liftEither
Run Code Online (Sandbox Code Playgroud)
欢迎对上述代码进行任何改进!
| 归档时间: |
|
| 查看次数: |
326 次 |
| 最近记录: |