我试图在readIO
上挑选read
,并写下这两段摘录
> 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,因此我应该能够几乎总是捕获异常。 / p>
readIO
并未用于我所见过的许多片段/示例/教程中,但是在该类型中出现错误的可能性似乎是一件好事,并收集所有内容Read a
的单个IO中的mapM
比使用普通map
的第一个示例更早产生错误。快速失败通常是令人垂涎的财产。
我是否应该使用read
s替换所有readIO
?
答案 0 :(得分:5)
没有。 readIO
是邪恶的。与read
类似,它应被视为部分功能。如果确保解析失败永远不会发生,或者你只是查看GHCi中的一些内容,那么read
就可以了(或多或少)。
如果您想要抓住解析失败,那么将正确显式化,不要只是把它当作IO
monad。 reads
是一个简单的选项,对于更高级的东西,使用像parsec这样的完整解析库。