Haskell的Prelude.read为什么不返回Maybe?


108

是否有充分的理由解释为什么Prelude.read是

read :: Read a => String -> a

而不是返回Maybe值?

read :: Read a => String -> Maybe a

由于字符串可能无法解析为Haskell,因此后者会更自然吗?

甚至是Either String aLeft如果没有解析,原始的字符串在哪里,如果有Right则返回结果?

编辑:

我并不是想让别人为我写一个相应的包装器。只是想确保这样做是安全的。


14
为什么不take接受任何东西Num a => a?为什么有fmapfor列表的特殊情况?为什么实例Functor不是必需的Monad?我希望答案与这些及相关问题的答案相似。

3
好吧,这就是为什么我这么说的原因,没有选择的理由是没有充分的理由。尽管我也怀疑可能没有,例如您所举的著名示例,但值得一提的是确保编写自己的包装程序不会在下游产生不可预见的问题。
Bilal Barakat

希望readMaybe很快会添加一个功能。
2011

好点@delnan,但不take应该Integral n => n -> [a] -> [a]吗?
Doug McClean

@DougMcClean:是的,实际上应该是Integral,不是Num-脑子放屁。

Answers:


106

编辑:从GHC 7.6开始,readMaybe可在Text.Read基本软件包的模块中找到,以及readEitherhttp://hackage.haskell.org/packages/archive/base/latest/doc/html/Text-Read.html#v:阅读也许


好问题!读取类型本身不会很快改变,因为这会破坏很多事情。但是,应该有一个maybeRead功能。

为什么不在那里?答案是“惯性”。有一个08年的讨论,其得到通过在讨论出轨“失败”。

好消息是,人们被说服力十足,开始摆脱图书馆的失败。坏消息是该提案在改组中失败了。这里应该是这样的功能,但一个很容易写(并有漂浮的许多代码库非常类似的版本不计其数)。

另请参阅此讨论

我个人使用安全包中的版本。


30

是的,使用返回Maybe的read函数会很方便。您可以自己做一个:

readMaybe :: (Read a) => String -> Maybe a
readMaybe s = case reads s of
              [(x, "")] -> Just x
              _ -> Nothing

3
谢谢!希望编辑不要忘恩负义!:)只是想说清楚,我不是出于懒惰...
Bilal Barakat

6
如果@augustss无法提供,则可能没有更好的答案。
约翰L,

2
我认为原始设计中从未讨论过可能的版本。这些事情中的许多随着经验变得显而易见,但很难预测。
2011

读取返回列表的原因是针对存在多个有效解析的情况。也许情况介于读取和读取之间。
克里斯·库克莱维奇

我认为这需要Read areadMaybe :: Read a => String -> Maybe a
typeclass

15

除了惯性和/或不断变化的见解之外,另一个原因可能是具有可以充当的逆函数的函数在美学上令人愉悦show。也就是说,你希望那read . show是标识(这是一个实例类型ShowRead),并且show . read是在范围内的身份show(即show . read . show == show

Maybe类型中具有read破坏与的对称性show :: a -> String


感谢您添加新角度!这就说得通了。但是要干净利落地做到这一点,让show和read都产生一个独特的类型(比如说“ ParseableString”)是否有意义?
比拉勒·巴拉卡特

1
@BilalBarakat:独特的类型可能是newtype ValidShow a = ValidShow String。幻像类型使其更安全。
yairchu

9
这是一个有趣的观点,但最终是错误的对称性。程序员应该重视正确性而不是美学。
马特·芬威克

1
@yairchu对我来说,您对幻影类型的含义不是立即很明显,所以我会澄清一下,以防其他人像我一样感到困惑。您打算使用showThing :: Show a => a -> ValidShow areadThing :: Read a => ValidShow a -> a之类的东西,以便在ValidShow对象中记住所显示事物的类型。这样你不会写readThing (showThing True) :: String
amalloy

12

正如@augustss指出的那样,您可以创建自己的安全读取功能。但是,他的readMaybe并不完全与read保持一致,因为它不会忽略字符串末尾的空格。(我曾经犯过这个错误,我不太记得上下文了)

查看Haskell 98报告中read定义,我们可以对其进行修改,以实现readMaybe与完全一致的read,这也不太方便,因为它所依赖的所有功能都在Prelude中进行了定义:

readMaybe        :: (Read a) => String -> Maybe a
readMaybe s      =  case [x | (x,t) <- reads s, ("","") <- lex t] of
                         [x] -> Just x
                         _   -> Nothing

1
谢谢!+1提醒我注意空白问题,以前没有明确指出过。
Bilal Barakat

3
请注意,如果您只是使用该safe软件包,则会获得readMaybe可用版本的正确版本(称为readMay该版本,并且与此版本相同。)
Neil Mitchell

8

readMaybe现在,此功能(称为)出现在Haskell的序幕中!(以当前基数为准-4.6)


2
好吧,链接的文本说它是在Text.Read中,而不是在Prelude中(可能已更改),但是,它仍然对我有帮助!
卡皮丘2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.