Haskell:readMay是如何评估的?

时间:2015-03-04 13:57:00

标签: haskell lazy-evaluation

当一段特定的代码困惑我时,我正在看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

2 个答案:

答案 0 :(得分:3)

如果无法确定readMay的结果类型,则代码将无法以“模糊类型”错误进行编译。它不会评估为Nothing

那你为什么不得到那个错误? Haskell可以通过首先查看case语句中的类型来确定类型。然而,这并不意味着首先评估内部 - 它不是,它只是首先推断的类型。类型检查和推断在编译时发生,并且与评估完全分开。类型推断的顺序不会影响评估的顺序。

答案 1 :(得分:3)

Haskell决定编译时的类型。它要么指出readMay的返回类型应该是什么,要么由于类型错误而拒绝编译代码。

当代码运行时,Haskell已经“知道”应该返回的readMay类型。如果实际呈现的字符串无法解析,您将获得Nothing

简而言之,懒惰评估无关。这是关于编译时的运行时。 [如果你只是从GHCi运行它,那可能就不那么明显了。]