【问题标题】:When should I prefer readIO over read? (or vice-versa)我什么时候应该更喜欢 readIO 而不是 read? (或相反亦然)
【发布时间】:2014-09-09 20:04:21
【问题描述】:

我试图在选择 readIO 而不是 read 时权衡取舍,我写了这 2 个 sn-ps

> map read . words <$> getLine :: IO [Int]
1 2 a
[1,2,*** Exception: Prelude.read: no parse
> mapM readIO . words =<< getLine :: IO [Int]
1 2 a
*** Exception: user error (Prelude.readIO: no parse)

我知道在纯代码中抛出异常(就像 read 一样)通常很糟糕,但通常我总是在 IO monad 中使用 read,因此我应该几乎总是能够捕获异常。

readIO 并没有在我所看到的那么多 sn-ps/examples/tutorials 中使用,但是 otoh 携带类型错误的可能性似乎是一件好事,并收集所有 Read a in带有mapM 的单个 IO 产生的错误早于带有纯 map 的第一个示例。快速失败通常是令人垂涎的属性。

我应该四处走走,用readIOs 替换所有reads 吗?

【问题讨论】:

    标签: haskell


    【解决方案1】:

    没有。 readIO 是邪恶的。像read 一样,它应该被认为是一个偏函数。 read 很好(或多或少),如果您确保永远不会发生解析失败,或者您只是检查 GHCi 中的一些内容。

    如果你想正确地捕获解析失败,那么正确地明确指出,不要只是把它扔到IO monad。 reads 是一个简单的选项,对于更高级的东西,请使用完整的解析库,如 parsec。

    【讨论】:

    • readIOread 更邪恶吗? (对我来说,您似乎是在暗示)
    • 因为它滥用IO 进行与IO 无关的错误处理。只有通过事先确保解析成功来防止错误发生才可以;但是你也可以使用read 并且不需要随身携带IO monad。
    • 有道理。我想强调的是,这不是您所说的“生产代码”,而是在输入众所周知的情况下使用的代码,您必须避免包含 parsecoptparse-applicative 等外部库(在线思考编码比赛)
    • @berdario 即使这样,导入 Text.Read 并使用 readMaybe 或仅使用读取。它们让您纯粹使用标准库来处理失败的解析。总是最好处理好错误,即使是练习代码也是如此。让自己养成这种习惯是值得的。
    猜你喜欢
    • 2015-09-10
    • 2017-10-21
    • 2022-01-08
    • 2011-05-10
    • 2017-12-21
    • 2010-11-14
    • 2011-12-07
    • 2010-10-23
    • 2018-01-22
    相关资源
    最近更新 更多