gpt4 book ai didi

haskell - 仆人处理程序中的任一计算

转载 作者:行者123 更新时间:2023-12-04 16:04:02 27 4
gpt4 key购买 nike

一个 servant-server HandlerExceptT 上的新类型包装器,并且有 MonadThrow 的实例, MonadCatch , MonadError , ETC。

这可能是一个有点做作的例子,但它显示了我经常面临的一个问题:

在处理程序中,我想调用三个返回 Either String Int 的函数,然后执行 Int -> Int -> Int -> IO (Either SomeError Text) 类型的计算,取三个Int s 从以前开始。

我应该如何构建此代码以确保尽早返回错误?

我看到我可以使用 EitherMonad实例“折叠”前三个 Either String Int计算成例如Either String (Int,Int,Int) ,然后绑定(bind)IO计算到某个结果值,然后使用 case决定是返回成功的结果还是使用throwErrorSomeError类型(转换后?),但我希望能够如下所示:

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)

是否可以编写类似于上面的代码?

最佳答案

假设你有一个函数 strToServantErr :: String -> ServantErr用于转换 f,g,h 返回的错误进入可以由您的处理程序返回的错误,然后我们可以使用:

  • liftEither 获取 Either String Int转入 ExceptT String s。
  • withExceptT ExceptT String 转换至ExceptT ServantErr根据 Handler 的要求.

  • x1 <- withExceptT strToServantErr $ liftEither f

    当你这样做三遍时,我们可以使用 mapM 使它更整洁:
    [x1, x2, x3] <- mapM (withExceptT strToServantErr . liftEither) [f, g, h]

    现在我们已经对参数进行了排序,我们可以使用相同的想法来修复返回。重命名您的 convertError函数到 someErrorToServantErr为了统一并假设它的类型为 SomeError -> ServantErr ,那么我们可以这样做:
    result <- liftIO $ a x1 x2 x3
    withExceptT someErrorToServantErr $ liftEither result

    我们打开 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

    这将尽快失败,并根据需要转换错误,虽然它很密集,但希望不是那么难以理解。

    你也可以走 Applicative 路线,虽然我找不到让它特别好的方法(虽然我没有使用过 applicative functors,但我可能错过了一些有用的技巧):
    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

    欢迎对上述代码进行任何改进!

    关于haskell - 仆人处理程序中的任一计算,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49527770/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com