【发布时间】:2014-04-24 22:22:43
【问题描述】:
我正在使用 GHC-7.8.2 测试 Write yourself a Scheme in 48 hours 的代码,这给了我一个关于歧义的错误,我不记得在以前的 GHC 版本中遇到过。 摘录如下,标出问题行:
data LispVal = Atom String
| List [LispVal]
| DottedList [LispVal] LispVal
| Number Integer
| String String
| Bool Bool
unpackNum :: LispVal -> Integer
unpackNum (Number n) = n
unpackNum (String n) = let parsed = reads n in --problem line
if null parsed
then 0
else fst $ parsed !! 0
unpackNum (List [n]) = unpackNum n
unpackNum _ = 0
,错误提示:
No instance for (Read a0) arising from a use of ¡®parsed¡¯
The type variable ¡®a0¡¯ is ambiguous
Note: there are several potential instances:
instance Read a => Read (Control.Applicative.ZipList a)
-- Defined in ¡®Control.Applicative¡¯
instance Read () -- Defined in ¡®GHC.Read¡¯
instance (Read a, Read b) => Read (a, b) -- Defined in ¡®GHC.Read¡¯
...plus 26 others
如果我将问题行更改为
unpackNum (String n) = let parsed = reads n ::[(Integer,String)] in
然后一切正常。
我不明白为什么 GHC 无法从 unpackNum 的签名中推断出 ReadS 的类型。有人能解释一下是什么触发了错误吗?
(
-- 编辑--
只是一些跟进。据我了解,函数类型unpackNum :: LispVal -> Integer 以及fst $ parsed !! 0 是它的返回值这一事实表明parsed 的类型为[(Integer,b)],而从type ReadS a = String -> [(a,String)] 来看,parsed 应该是[(a, String)] .难道这两种类型不应该统一为[(Integer, String)],固定为parsed的类型吗?
有人能解释一下为什么NoMonomorphismRestriction 会打破上述推理吗?
-- 编辑2--
从答案中,我可以理解NoMonomorphismRestriction 是如何导致这里出现问题的。不过,我不明白的是,这种“同一表达式的两种类型”行为如何与 Haskell 中的懒惰相一致。在示例中,parsed 或 reads n 在一个块中是相同的表达式,并且应该只计算一次。怎么可能第一次评估有a,第二次有Integer?
)
谢谢,
【问题讨论】:
-
代码只是用 ghc-7.8.2 为我编译 ...
-
@kosmikus:也在 ghc-7.8.2 上,我看到与 OP 相同的错误。