Haskell 服务处理程序中的任一计算
A是Haskell 服务处理程序中的任一计算,haskell,monad-transformers,servant,Haskell,Monad Transformers,Servant,A是例外项上的新类型包装,具有MonadThrow、MonadCatch、MonadError等实例 这可能是一个有点做作的例子,但它显示了我经常面临的一个问题: 在处理程序中,我想调用三个返回字符串Int的函数,然后执行类型Int->Int->Int->IO(SomeError Text)的计算,从前面取三个Int 我应该如何构造此代码以确保尽早返回错误 我发现我可以使用other的Monad实例将前三个other String Int计算“折叠”为例如other String(Int,Int
例外项上的新类型包装,具有MonadThrow
、MonadCatch
、MonadError
等实例
这可能是一个有点做作的例子,但它显示了我经常面临的一个问题:
在处理程序中,我想调用三个返回字符串Int
的函数,然后执行类型Int->Int->Int->IO(SomeError Text)
的计算,从前面取三个Int
我应该如何构造此代码以确保尽早返回错误
我发现我可以使用other
的Monad
实例将前三个other String Int
计算“折叠”为例如other String(Int,Int,Int)
,然后将IO
计算绑定到某个结果值,然后使用case
来决定是返回一个成功的结果,还是使用throwError
来抛出SomeError
类型(转换后?),但我希望能够如下所示:
f, g, h :: Either String Int
a :: Int -> Int -> Int -> IO (Either SomeError Text)
myHandler :: Handler Text
myHandler = do
x1 <- f
x2 <- g
x3 <- h
liftIO $ convertError $ (a x1 x2 x3)
f,g,h::字符串Int
a::Int->Int->Int->IO(某个错误文本)
myHandler::Handler文本
myHandler=do
x1假设您有一个函数strotservanterr::String->ServantErr
,用于将f,g,h
返回的错误转换为处理程序可以返回的错误,那么我们可以使用:
- 将
任一字符串Int
s转换为ExceptT字符串
s
- 根据
处理程序的要求,将ExceptT字符串
转换为ExceptT ServantErr
现在我们已经对参数进行了排序,我们可以使用相同的想法来修复返回。将您的convertError
函数重命名为someErrorToServantErr
,以实现一致性,并假设它具有类型SomeError->ServantErr
,则我们可以执行以下操作:
result <- liftIO $ a x1 x2 x3
withExceptT someErrorToServantErr $ liftEither result
它将尽快失败,并根据需要转换错误,虽然它很密集,但希望不是那么不可读
您也可以选择应用程序路线,尽管我找不到一种特别好的方法(虽然我很少使用应用程序函子,但我可能缺少一些有用的技巧):
myHandler::Handler文本
myHandler=do
让[x1,x2,x3]=map(liftMapE-strotservanterr)[f,g,h]-[Handler-Int]
tmp您可能有一个问题,即处理程序
是一个例外的ServantErr
,但您的错误是字符串
s。我们可以假设您有一个函数String->ServantErr
,可以用来转换错误吗?您可以更进一步,在ExceptT monad(或类似的东西)中使用自定义错误类型,并使用wingserver
(请参阅)。@AlpMestanogullari噢,酷。我并不知道关于仆人的任何事情,所以希望OP能看到你的评论并发现它很有用。
[x1, x2, x3] <- mapM (withExceptT strToServantErr . liftEither) [f, g, h]
result <- liftIO $ a x1 x2 x3
withExceptT someErrorToServantErr $ liftEither result
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
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