gpt4 book ai didi

Haskell 方法通过中止对多个项目进行错误检查

转载 作者:行者123 更新时间:2023-12-03 14:55:32 24 4
gpt4 key购买 nike

Haskell 函数检查多个不同条件并在失败时返回错误消息的好方法是什么?

在 Python 或类似语言中,这很简单:

if failure_1:
return "test1 failed"
if failure_2:
return "test2 failed"
...
if failure_n:
return "testn failed"
do_computation

如果没有 Haskell 中任意嵌套的 case/if 语句,你如何做到这一点?

编辑:某些测试条件可能需要 IO 将任何测试结果放入 IO monad。我相信这会给许多解决方案带来麻烦。

最佳答案

所以,你被困在 IO ,并且您想检查一堆没有大量嵌套的条件 if s。我希望你能原谅我通过回答的方式在 Haskell 中解决更一般的问题。

抽象地考虑这需要如何表现。检查条件有两种结果之一:

  • 成功,在这种情况下程序运行函数的其余部分
  • 失败,在这种情况下,程序会丢弃函数的其余部分并返回错误消息。

  • 检查多个条件可以递归查看;每次它运行“函数的其余部分”时,它都会遇到下一个条件,直到到达最后一步,它只返回结果。现在,作为解决问题的第一步,让我们使用该结构将事物分解——所以基本上,我们希望将一堆任意条件变成可以组合成多条件函数的片段。关于这些作品的性质,我们可以得出什么结论?

    1)每件可以返回两种不同类型中的一种;错误消息或下一步的结果。

    2)每个部分必须决定是否运行下一步,所以在组合步骤时我们需要给它代表下一步的函数作为参数。

    3)由于每个部分都希望得到下一步,为了保持统一的结构,我们需要一种方法将最终的无条件步骤转换为看起来与条件步骤相同的东西。

    第一个要求显然表明我们需要像 Either String a 这样的类型。对于我们的结果。现在我们需要一个组合函数来满足第二个要求,以及一个包装函数来满足第三个要求。此外,在组合步骤时,我们可能希望访问上一步的数据(例如,验证两个不同的输入,然后检查它们是否相等),因此每个步骤都需要将上一步的结果作为参数。

    所以,调用每一步的类型 err a简而言之,其他函数可能有哪些类型?
    combineSteps :: err a -> (a -> err b) -> err b
    wrapFinalStep :: a -> err a

    那么现在,那些类型签名看起来非常熟悉,不是吗?

    这种“运行可能会因错误消息而提前失败的计算”的一般策略确实适用于单子(monad)实现。事实上 mtl package已经有一个了。对于这种情况,更重要的是,它还有一个 monad 转换器,这意味着您可以将错误 monad 结构添加到另一个 monad 上——例如 IO .

    所以,我们可以只导入模块,制作一个类型同义词来包装 IO在温暖的模糊中 ErrorT ,然后你就走了:
    import Control.Monad.Error

    type EIO a = ErrorT String IO a

    assert pred err = if pred then return () else throwError err

    askUser prompt = do
    liftIO $ putStr prompt
    liftIO getLine

    main :: IO (Either String ())
    main = runErrorT test

    test :: EIO ()
    test = do
    x1 <- askUser "Please enter anything but the number 5: "
    assert (x1 /= "5") "Entered 5"
    x2 <- askUser "Please enter a capital letter Z: "
    assert (x2 == "Z") "Didn't enter Z"
    x3 <- askUser "Please enter the same thing you entered for the first question: "
    assert (x3 == x1) $ "Didn't enter " ++ x1
    return () -- superfluous, here to make the final result more explicit

    运行结果 test ,正如您所料,是 Right ()成功,或 Left String对于失败, String是适当的消息;如果 assert返回失败,将不执行以下任何操作。

    用于测试 IO 的结果您可能会发现编写类似于 assert 的辅助函数最容易。取而代之的是 IO Bool 的参数,或其他一些方法。

    还要注意 liftIO 的使用。转换 IO将操作转化为 EIO 中的值, 和 runErrorT运行 EIO操作并返回 Either String a值与整体结果。您可以阅读 monad transformers如果你想要更多细节。

    关于Haskell 方法通过中止对多个项目进行错误检查,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2138385/

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