什么是 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
会更好吗?
What exactly is AllowAmbiguousTypes
?
来自latest GHC docs、"a type ty
is ambiguous if and only if ((undefined :: ty) :: ty)
would fail to typecheck"。扩展 AllowAmbiguousTypes
只是禁用此检查 - 它不会允许错误类型的程序通过。
Why is it needed to make this particular code work?
为了在使用 g
时检查 RealFloat a
是否满足,GHC 需要知道 a
是什么。你没有办法(在 vanilla Haskell1 中)告诉 GHC a
应该是什么,因为 a
在 [= 的类型中没有出现在其他地方16=]。再多的注释也不能让你使用 g
而不会出现类型变量不明确的错误。
但是,如果您不在任何地方使用 g
,您仍然可以通过打开 AllowAmbiguousTypes
.[=45 来编译您的代码=]
I fear that adding AllowAmbiguousTypes
is giving me more than I really want in this particular code. It sounds scary. It sounds like it will make Haskell's type system less safe, perhaps in other areas that have nothing to do with this particular code. Are these fears unfounded?
是的,它们是:歧义检查可以让您捕获不能(在普通 Haskell 中没有 TypeApplications
1)的定义在不导致歧义类型变量错误的情况下使用。禁用此检查仅意味着当您使用表达式(或函数)而不是在其定义站点时,您将看到不明确的类型变量消息。
Are there any alternatives? In this case, it seems like Haskell is inserting a a0
type variable that I never asked for. Is there no extension to tell Haskell not to create these extraneous type variables - and only use those that I explicitly told it to add with my own explicit forall a
?
a0
来自我在本答案开头提到的歧义检查。 GHC 只是使用名称 a0
来表明它不同于 a
。歧义检查基本上只是尝试 typecheck
((undefined :: forall a. RealFloat a => Bool) :: forall a0. RealFloat a0 => Bool)
AllowAmbiguousTypes
删除此检查。我不认为有一个扩展只对具有显式 forall
s 的类型签名禁用歧义检查(尽管这可能很整洁有用!)。
Would you say that AllowAmbiguousTypes
is a misnomer? Would it have been better named as AllowUnusedTypeVariables
?
给事物命名很难。 :)
当前名称引用了您在未启用扩展程序的情况下遇到的错误类型,因此它不是一个坏名称。我想这是一个见仁见智的问题。 (很多人也希望 Monad
被称为 FlatMapAble
。)
1 在 TypeApplications
(这是 GHC 8.0 的一个相对较新的扩展)之前,确实没有办法在不获取的情况下使用触发歧义检查的表达式模棱两可的类型变量错误,因此 AllowAmbiguousTypes
的用处不大。
代码
{-# 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
会更好吗?
What exactly is
AllowAmbiguousTypes
?
来自latest GHC docs、"a type ty
is ambiguous if and only if ((undefined :: ty) :: ty)
would fail to typecheck"。扩展 AllowAmbiguousTypes
只是禁用此检查 - 它不会允许错误类型的程序通过。
Why is it needed to make this particular code work?
为了在使用 g
时检查 RealFloat a
是否满足,GHC 需要知道 a
是什么。你没有办法(在 vanilla Haskell1 中)告诉 GHC a
应该是什么,因为 a
在 [= 的类型中没有出现在其他地方16=]。再多的注释也不能让你使用 g
而不会出现类型变量不明确的错误。
但是,如果您不在任何地方使用 g
,您仍然可以通过打开 AllowAmbiguousTypes
.[=45 来编译您的代码=]
I fear that adding
AllowAmbiguousTypes
is giving me more than I really want in this particular code. It sounds scary. It sounds like it will make Haskell's type system less safe, perhaps in other areas that have nothing to do with this particular code. Are these fears unfounded?
是的,它们是:歧义检查可以让您捕获不能(在普通 Haskell 中没有 TypeApplications
1)的定义在不导致歧义类型变量错误的情况下使用。禁用此检查仅意味着当您使用表达式(或函数)而不是在其定义站点时,您将看到不明确的类型变量消息。
Are there any alternatives? In this case, it seems like Haskell is inserting a
a0
type variable that I never asked for. Is there no extension to tell Haskell not to create these extraneous type variables - and only use those that I explicitly told it to add with my own explicitforall a
?
a0
来自我在本答案开头提到的歧义检查。 GHC 只是使用名称 a0
来表明它不同于 a
。歧义检查基本上只是尝试 typecheck
((undefined :: forall a. RealFloat a => Bool) :: forall a0. RealFloat a0 => Bool)
AllowAmbiguousTypes
删除此检查。我不认为有一个扩展只对具有显式 forall
s 的类型签名禁用歧义检查(尽管这可能很整洁有用!)。
Would you say that
AllowAmbiguousTypes
is a misnomer? Would it have been better named asAllowUnusedTypeVariables
?
给事物命名很难。 :)
当前名称引用了您在未启用扩展程序的情况下遇到的错误类型,因此它不是一个坏名称。我想这是一个见仁见智的问题。 (很多人也希望 Monad
被称为 FlatMapAble
。)
1 在 TypeApplications
(这是 GHC 8.0 的一个相对较新的扩展)之前,确实没有办法在不获取的情况下使用触发歧义检查的表达式模棱两可的类型变量错误,因此 AllowAmbiguousTypes
的用处不大。