![](/img/trans.png)
[英]In Haskell, why are types ambiguous even with AllowAmbiguousTypes enabled?
[英]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 的类型系统的安全性,也许在与此特定代码无关的其他领域。 这些恐惧是没有根据的吗?a0
类型变量。 是否没有扩展告诉 Haskell 不要创建这些无关的类型变量 - 并且只使用我明确告诉它添加我自己的显式forall a
变量?AllowAmbiguousTypes
用词不当吗? 将它命名为AllowUnusedTypeVariables
会更好吗?
AllowAmbiguousTypes
到底是什么?
从最新的 GHC 文档中,“类型ty
是不明确的当且仅当((undefined:: ty):: ty)
无法进行类型检查”。 扩展名AllowAmbiguousTypes
只是禁用此检查 - 它不会允许错误类型的程序通过。
为什么需要使这个特定代码工作?
为了检查每当使用g
时RealFloat a
是否满足,GHC 需要知道a
是什么。 你没有办法(在 vanilla Haskell 1中)告诉 GHC a
应该是什么,因为a
在g
的类型中没有出现在其他地方。 再多的注解也不能让你在使用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
类的东西。)
1在TypeApplications
(这是 GHC 8.0 的一个相对较新的扩展)之前,确实没有办法使用触发歧义检查的表达式而不会出现歧义类型变量错误,因此AllowAmbiguousTypes
的用处要小得多。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.