什么是AllowAmbiguousTypes以及为什么在这个"forall"示例中需要它?

has*_*lHQ 12 haskell types ghc

代码

{-# LANGUAGE ScopedTypeVariables, TypeApplications #-}

-- I know this particular example is silly.
-- But that's not the point here.
g :: forall a . RealFloat a => Bool
g = True

main :: IO ()
main = print (g @Double)
Run Code Online (Sandbox Code Playgroud)

无法在GHC 8.0上编译并出现错误

• Could not deduce (RealFloat a0)
      from the context: RealFloat a
        bound by the type signature for:
                   g :: RealFloat a => Bool
        at app/Main.hs:3:6-35
      The type variable ‘a0’ is ambiguous
    • In the ambiguity check for ‘g’
      To defer the ambiguity check to use sites, enable AllowAmbiguousTypes
      In the type signature:
        g :: forall a. RealFloat a => Bool
Run Code Online (Sandbox Code Playgroud)

所以添加AllowAmbiguousTypes将使代码编译.

这是我的问题:

  • 到底是AllowAmbiguousTypes什么?
  • 为什么需要使这个特定的代码工作?
  • 我担心AllowAmbiguousTypes在这个特定的代码中添加比我真正想要的更多.这听起来很吓人.听起来它会使Haskell的类型系统不那么安全,也许在与这个特定代码无关的其他领域.这些恐惧是否毫无根据?
  • 还有其他选择吗?在这种情况下,似乎Haskell正在插入一个a0我从未要求的类型变量.是否没有扩展来告诉Haskell不要创建这些无关的类型变量 - 并且只使用那些我明确告诉它用我自己的显式添加的变量forall a
  • 由于user2407038的评论添加了一个问题:你会说这AllowAmbiguousTypes是用词不当吗?它会更好地命名为AllowUnusedTypeVariables

Ale*_*lec 16

到底是AllowAmbiguousTypes什么?

最新的GHC文档来看," ty当且仅当((undefined :: ty) :: ty)不能进行类型检查时,类型才是模糊的".扩展AllowAmbiguousTypes只是禁用此检查 - 它不会允许错误的程序通过.

为什么需要使这个特定的代码工作?

为了检查RealFloat a每次g使用时是否满足,GHC需要知道什么a是.你没有办法(在香草Haskell 1中)告诉GHC a应该是什么,因为a在类型中没有其他地方发生g.如果没有g模糊的类型变量错误,您将无法使用任何注释.

但是,如果您不在任何地方使用 g,您仍然可以通过打开来编译代码AllowAmbiguousTypes.

我担心AllowAmbiguousTypes在这个特定的代码中添加比我真正想要的更多.这听起来很吓人.听起来它会使Haskell的类型系统不那么安全,也许在与这个特定代码无关的其他领域.这些恐惧是否毫无根据?

是的,它们是:模糊检查可以捕获不能使用(在没有TypeApplications1的 vanilla Haskell中)而不会导致模糊类型变量错误的定义.禁用此检查只意味着当您使用表达式(或函数)而不是在其定义站点时,您将看到不明确的类型变量消息.

还有其他选择吗?在这种情况下,似乎Haskell正在插入一个a0我从未要求的类型变量.是否没有扩展来告诉Haskell不要创建这些无关的类型变量 - 并且只使用那些我明确告诉它用我自己的显式添加的变量forall a

a0是来自我在本回答开头提到的含糊不清的检查.GHC只是使用该名称a0来明确它与之不同a.歧义检查基本上只是试图进行类型检查

((undefined :: forall a. RealFloat a => Bool) :: forall a0. RealFloat a0 => Bool)
Run Code Online (Sandbox Code Playgroud)

AllowAmbiguousTypes删除此检查.我不认为有一个扩展只禁用带有显式foralls的类型签名的歧义检查(虽然这可能是整洁有用的!).

你会说那AllowAmbiguousTypes是用词不当吗?它会更好地命名为AllowUnusedTypeVariables

命名事情很难.:)

当前名称引用了未启用扩展的错误类型,因此它不是一个坏名称.我想这是一个意见问题.(许多人也希望Monad被称为类似的东西FlatMapAble.)


1之前TypeApplications(这是GHC 8.0的一个相对较新的扩展),实际上没有办法使用触发歧义检查的表达式而不会产生模糊的类型变量错误,所以没AllowAmbiguousTypes那么有用.