与 TypeApplications 一起使用时,AllowAmbiguousTypes 有多危险?

How dangerous is AllowAmbiguousTypes when used with TypeApplications?

AllowAmbiguousTypes extension when used with the TypeApplications 扩展有多危险?

GHC 手册给出了以下不明确类型的示例:

class C a

f :: C a => Int
f = 3

当不使用 AllowAmbiguousTypes 时编译失败并显示以下消息:

file.hs:8:6: error:
    • Could not deduce (C a0)
      from the context: C a
        bound by the type signature for:
                   f :: forall a. C a => Int
        at file.hs:8:6-15
      The type variable ‘a0’ is ambiguous
    • In the ambiguity check for ‘f’
      To defer the ambiguity check to use sites, enable AllowAmbiguousTypes
      In the type signature: f :: C a => Int
  |
8 | f :: C a => Int
  |      ^^^^^^^^^^

使用 AllowAmbiguousTypes,编译正确。

但是,下面的示例即使使用 AllowAmbiguousTypes 也无法编译:

class C a

f :: C a => Int
f = 3

g :: C a => Int
g = f

尝试编译时出现以下错误:

file.hs:12:5: error:
    • Could not deduce (C a0) arising from a use of ‘f’
      from the context: C a
        bound by the type signature for:
                   g :: forall a. C a => Int
        at file.hs:11:1-15
      The type variable ‘a0’ is ambiguous
    • In the expression: f
      In an equation for ‘g’: g = f
   |
12 | g = f
   |     ^

这可以通过启用TypeApplications并像下面这样写:

class C a

f :: C a => Int
f = 3

g :: forall a. C a => Int
g = f @a

AllowAmbiguousTypes 听起来很吓人,但根据 GHC 手册中的描述,它似乎相当良性,尤其是与 TypeApplications.

一起使用时

AllowAmbiguousTypes不会导致运行时错误吧?

这种 AllowAmbiguousTypesTypeApplications 的组合似乎也用在一些非常流行的软件包中,比如 constraints.

Alexis King 在她的评论中指出了这一点;它应该提升到答案的水平。

AllowAmbiguousTypes is completely safe, in the sense that it is perfectly sound, will not make the compiler diverge, and cannot lead to runtime errors. It was just mostly useless prior to the introduction of TypeApplications. The combination of the two is a perfectly reasonable thing.