繁体   English   中英

什么是 AllowAmbiguousTypes 以及为什么在此“forall”示例中需要它?

[英]What is AllowAmbiguousTypes and why is it needed in this "forall" example?

代码

{-# 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)

无法在 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

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

这是我的问题:

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

AllowAmbiguousTypes到底是什么?

最新的 GHC 文档中,“类型ty是不明确的当且仅当((undefined:: ty):: ty)无法进行类型检查”。 扩展名AllowAmbiguousTypes只是禁用此检查 - 它不会允许错误类型的程序通过。

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

为了检查每当使用gRealFloat a是否满足,GHC 需要知道a是什么。 你没有办法(在 vanilla Haskell 1中)告诉 GHC a应该是什么,因为ag的类型中没有出现在其他地方。 再多的注解也不能让你在使用g时不会出现类型变量不明确的错误。

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

我担心在这个特定代码中添加AllowAmbiguousTypes会比我真正想要的更多。 听起来很可怕。 听起来它会降低 Haskell 的类型系统的安全性,也许在与此特定代码无关的其他领域。 这些恐惧是没有根据的吗?

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

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

a0来自我在这个答案开头提到的歧义检查。 GHC 只是使用名称a0来表明它与a不同。 歧义检查基本上只是尝试进行类型检查

((undefined :: forall a. RealFloat a => Bool) :: forall a0. RealFloat a0 => Bool)

AllowAmbiguousTypes删除此检查。 我不认为有一个扩展仅对具有显式forall的类型签名禁用歧义检查(尽管这可能很简洁且有用。)。

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

命名事物很难。 :)

当前名称引用了您在未启用扩展的情况下遇到的错误类型,因此它不是一个坏名称。 我想这是一个见仁见智的问题。 (很多人也希望Monad被称为FlatMapAble类的东西。)


1TypeApplications (这是 GHC 8.0 的一个相对较新的扩展)之前,确实没有办法使用触发歧义检查的表达式而不会出现歧义类型变量错误,因此AllowAmbiguousTypes的用处要小得多。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM