带有HashMap的不明确的类型变量

时间:2012-12-06 20:32:14

标签: haskell

我最近开始玩haskell,我在使用HashMap时遇到了一个问题,可以用这个玩具示例来说明:

import Data.HashMap as HashMap

foo = HashMap.insert 42 53 HashMap.empty

这是我在解释器中加载文件或编译它时出现的错误:

Prelude List HashMap> :load TypeError.hs
[1 of 1] Compiling Main             ( TypeError.hs, interpreted )

TypeError.hs:3:22:
    Ambiguous type variable `k0' in the constraints:
      (Num k0) arising from the literal `42' at TypeError.hs:3:22-23
      (Ord k0) arising from a use of `insert' at TypeError.hs:3:7-20
      (Data.Hashable.Hashable k0)
        arising from a use of `insert' at TypeError.hs:3:7-20
    Possible cause: the monomorphism restriction applied to the following:
      foo :: Map k0 Integer (bound at TypeError.hs:3:1)
    Probable fix: give these definition(s) an explicit type signature
                  or use -XNoMonomorphismRestriction
    In the first argument of `insert', namely `42'
    In the expression: insert 42 53 empty
    In an equation for `foo': foo = insert 42 53 empty
Failed, modules loaded: none.
Prelude List HashMap>

但是如果我直接在解释器中定义完全相同的函数,我就不会收到错误:

Prelude List HashMap> let foo = HashMap.insert 42 53 HashMap.empty
Prelude List HashMap>

有没有人对此有任何线索?

感谢。

1 个答案:

答案 0 :(得分:6)

原因是ghci使用扩展默认规则,而编译器使用(默认情况下)defaulting rules specified in the language report

类Num中的歧义是最常见的,因此Haskell提供了另一种解决方法 - 使用默认声明:default(t1,...,tn)其中n≥0,每个ti必须是Num ti的类型成立。在发现模糊类型的情况下,如果出现以下情况,则模糊类型变量v是可以违约的:

  • v仅出现在C v形式的约束中,其中C是一个类,
  • 这些类中至少有一个是数字类(即Num或Num的子类),
  • 所有这些类都在Prelude或标准库中定义

相关规则是,只有在标准库中定义了所有涉及的类时,才会执行默认报告,但是密钥上的Hashable约束涉及不符合该要求的类。

因此编译器拒绝它,因为它无法解析由键产生的模糊类型变量,而ghci默认为Integer,因为如果涉及其他类,ghci也默认为。