Haskell: readMay 是如何评估的?
Haskell: how is readMay evaluated?
我在看 tutorial in School of Haskell 时,一段特定的代码让我感到困惑。在我看来,下面的代码片段不应该起作用,但它确实起作用了。在这种情况下,关于 readMay
的评估,我不太明白。
import Safe (readMay)
main = do
putStrLn "Please enter your birth year"
yearString <- getLine
case readMay yearString of
Nothing -> putStrLn "Invalid year"
Just year -> putStrLn $ "In 2020, you'll be " ++ show (2020 - year)
readMay yearString
(:t readMay = Read a => String -> Maybe a
) 不应该总是计算为 Nothing
,因为我没有强制其类型吗?为了让这段代码起作用,必须首先计算 case
语句的结果表达式,因为表达式 2020 - year
需要 year
属于 Num
类型类,从而允许 readMay yearString
评估为 Just year
.
如果无法确定 readMay
的结果类型,代码将无法编译并出现 "ambiguous type" 错误。它不会评估为 Nothing
.
那你为什么没有得到那个错误? Haskell可以先看case语句里面的类型来判断类型。然而,这并不意味着首先对内部进行评估 - 它不是,它只是首先推断类型。类型检查和推断发生在编译时,并且完全独立于求值。类型推断的顺序不影响求值顺序。
Haskell 决定 编译时 的类型。它要么弄清楚 readMay
的 return 类型应该是什么,要么由于类型错误而拒绝编译代码。
到代码 运行s 时,Haskell 已经 "knows" 什么类型 readMay
应该 returning。如果实际显示的字符串无法解析,您将得到 Nothing
.
简而言之,这与惰性评估无关。这是关于编译时间和 运行 时间的。 [如果你只是 运行从 GHCi 中获取它,这可能不是那么明显。]
我在看 tutorial in School of Haskell 时,一段特定的代码让我感到困惑。在我看来,下面的代码片段不应该起作用,但它确实起作用了。在这种情况下,关于 readMay
的评估,我不太明白。
import Safe (readMay)
main = do
putStrLn "Please enter your birth year"
yearString <- getLine
case readMay yearString of
Nothing -> putStrLn "Invalid year"
Just year -> putStrLn $ "In 2020, you'll be " ++ show (2020 - year)
readMay yearString
(:t readMay = Read a => String -> Maybe a
) 不应该总是计算为 Nothing
,因为我没有强制其类型吗?为了让这段代码起作用,必须首先计算 case
语句的结果表达式,因为表达式 2020 - year
需要 year
属于 Num
类型类,从而允许 readMay yearString
评估为 Just year
.
如果无法确定 readMay
的结果类型,代码将无法编译并出现 "ambiguous type" 错误。它不会评估为 Nothing
.
那你为什么没有得到那个错误? Haskell可以先看case语句里面的类型来判断类型。然而,这并不意味着首先对内部进行评估 - 它不是,它只是首先推断类型。类型检查和推断发生在编译时,并且完全独立于求值。类型推断的顺序不影响求值顺序。
Haskell 决定 编译时 的类型。它要么弄清楚 readMay
的 return 类型应该是什么,要么由于类型错误而拒绝编译代码。
到代码 运行s 时,Haskell 已经 "knows" 什么类型 readMay
应该 returning。如果实际显示的字符串无法解析,您将得到 Nothing
.
简而言之,这与惰性评估无关。这是关于编译时间和 运行 时间的。 [如果你只是 运行从 GHCi 中获取它,这可能不是那么明显。]