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 中获取它,这可能不是那么明显。]