【问题标题】:Haskell: how is readMay evaluated?Haskell:如何评估 readMay?
【发布时间】:2015-03-04 23:39:54
【问题描述】:

我正在查看tutorial in School of Haskell,当时一段特定的代码让我感到困惑。在我看来,下面的 sn-p 应该不起作用,但它确实有效。在这种情况下,对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 =&gt; String -&gt; Maybe a) 总是评估为Nothing,因为我没有强制它的类型?要使此代码正常工作,必须首先计算 case 语句的结果表达式,因为表达式 2020 - year 将要求 year 属于 Num 类型类,因此允许 readMay yearString 计算为Just year.

【问题讨论】:

  • 很好的例子。一开始,类型推断可能非常聪明。
  • 其实这里要使用的类型是模棱两可的。它仅因 GHC “魔法”而起作用 - 它默认类型为 readMay :: String -&gt; Maybe Integer。如果你打开警告,你会看到这个。
  • @user2407038 我想知道...我认为它一定是默认规则。

标签: haskell lazy-evaluation


【解决方案1】:

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

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

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

【讨论】:

  • 谢谢。事实上,当你只是 runhaskell source.hs 一切时,这并不是很明显。
【解决方案2】:

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

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

【讨论】: