为什么 `read "1" :: Maybe Int` 会进行类型检查?

Why will `read "1" :: Maybe Int` type check?

我想知道为什么read "1" :: Maybe Int会在运行时进行类型检查并抛出异常。

read 有可能 return 成为 Maybe a 吗?这就是 Text.Read.readMaybe 应该做的。

Prelude> read "1" :: Maybe Int
*** Exception: Prelude.read: no parse

简而言之:你解析Maybe a类型的文本表示,不是 a 作为非总函数,其中 Nothing 用于指定解析失败。

嗯,read 通常是 show 相反 。因此它将解析一个对象的表示,即经常如何将对象作为数据构造函数的级联写入一个对象。

现在 Maybe aShow 家族的一种类型,考虑到它包装的元素也是 Show 的一个实例,例如:

instance Show a => Show (Maybe a) where
    show Nothing = "Nothing"
    show (Just x) = "Just "++ show x

(实际上它有点复杂,因为它还会引入括号,以防您将 Just 1 包裹在 Just 中)。

所以反过来也可以解析。例如:

Prelude> read "<b>Nothing</b>" :: Maybe Int
Nothing
Prelude> read "<b>Just</b> 5" :: Maybe Int
Just 5

所以 Maybe a 作为 read 的一种类型并不意味着“非总”函数,而是解析Maybe a 类型。

因此它解析带有前缀 "Nothing""Just" 的字符串(并且还可以解析一些带有括号的 "expressions")。

I wonder why read "1" :: Maybe Int would type check

因为 "1" 的类型为 String,因此可以作为 read 的参数接受,而 Maybe Int 实现 Read,因此可以作为参数接受return Read.

类型

and throw an exception in runtime.

因为“1”不是 Maybe Int 的有效字符串表示形式。

Is it possible that read can ever return a Maybe a?

是的,例如 read "Just 42" :: Maybe IntJust 42read "Nothing" :: Maybe IntNothing

基本上,您可能从 show x 中得到的任何字符串,其中 x :: Maybe Int 也可以作为参数提供给 read 以获得 Maybe Int.

或者更一般地说,show x 的任何输出,其中 x :: TTShowRead 的一个实例,可能会被馈送到read 取回 T 类型的值——尽管实例当然可以任意定义,所以并不是每个实现 ReadShow 的类型都必须遵守 "contract".