代码
{-# 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
吗?答案 0 :(得分:15)
究竟是什么
AllowAmbiguousTypes
?
从latest GHC docs开始,“类型ty
是不明确的,当且仅当((undefined :: ty) :: ty)
无法进行类型检查时”。扩展程序AllowAmbiguousTypes
只是禁用此检查 - 它不会允许输入错误的程序。
为什么需要使这个特定代码有效?
为了在每次使用RealFloat a
时检查是否满足g
,GHC需要知道a
是什么。告诉GHC a
应该是什么a
,因为g
的类型不存在g
,所以你没有办法(在vanilla Haskell 1 中)。没有任何注释会让您使用g
而不会出现模糊的类型变量错误。
但是,如果您未在任何地方使用 AllowAmbiguousTypes
,您仍然可以通过启用AllowAmbiguousTypes
来编译代码。
我担心在这个特定的代码中添加
TypeApplications
比我真正想要的更多。这听起来很吓人。听起来它会使Haskell的类型系统不那么安全,也许在与这个特定代码无关的其他领域。这些恐惧是否毫无根据?
是的,它们是:模糊检查可以捕获不能使用的定义(在没有a0
1 的vanilla Haskell中),而不会导致模糊的类型变量错误。禁用此检查意味着当您使用表达式(或函数)而不是在其定义站点时,您将看到不明确的类型变量消息。
还有其他选择吗?在这种情况下,似乎Haskell正在插入一个我从未要求的
forall a
类型变量。是否没有扩展来告诉Haskell不要创建这些无关的类型变量 - 并且只使用那些我明确告诉它用我自己的显式a0
添加的变量?
a0
来自我在本回答开头提到的歧义检查。 GHC只使用名称a
来明确它与((undefined :: forall a. RealFloat a => Bool) :: forall a0. RealFloat a0 => Bool)
不同。歧义检查基本上只是试图进行类型检查
AllowAmbiguousTypes
forall
删除此检查。我不认为有一个扩展只禁用带有显式AllowAmbiguousTypes
s的类型签名的歧义检查(虽然这可能是整洁有用的!)。
你会说
AllowUnusedTypeVariables
是用词不当吗?它会更好地命名为Monad
吗?
命名事情很难。 :)
当前名称引用了未启用扩展程序时获得的错误类型,因此它不是一个错误的名称。我想这是一个意见问题。 (很多人也希望FlatMapAble
被称为TypeApplications
。
1 在AllowAmbiguousTypes
之前(这是GHC 8.0的一个相对较新的扩展),实际上没有办法使用触发歧义检查的表达式而不会出现模糊的类型变量错误,所以<form name="search" action="" method="post">
<h2>Include:</h2>
<div id="formtitle" class="formdiv">
<p> Current Job Title:</p><input id="jtitle" type="text" name="jobtitle" placeholder="Demand planner, Supply planner">
</div>
<div id="formcompany" class="formdiv">
<p> Current Company:</p><input id="cmpy" type="text" name="company" placeholder="GSK OR Danone">
</div>
<div id="formkeywords" class="formdiv">
<p> Keywords:</p><input id="kwrd" type="text" name="keywords" placeholder="(SAP OR JDE) AND FMCG">
</div>
<div id="formfirst" class="formdiv">
<p> First Name:</p><input id="fname" type="text" name="first">
</div>
<div id="formlast" class="formdiv">
<p> Last Name:</p><input id="lname" type="text" name="last">
</div>
<hr>
<h2> Exclude:</h2>
<div id="formnottitle" class="formdiv">
<p> Current Job Title:</p><input id="njtitle" type="text" name="notjobtitle" placeholder="Manager OR Consultant">
</div>
<div id="formnotcompany" class="formdiv">
<p> Current Company:</p><input id="ncmpy" type="text" name="notcompany" placeholder="Coke OR Pepsi">
</div>
<div id="formnotkeywords" class="formdiv">
<p> Keywords:</p><input id="nkwrd" type="text" name="notkeywords" placeholder="Recruiter OR Recruitment">
</div>
<div id="submit" class="formdiv">
<input type="button" id="onclick" value="Create Search"/>
</div>
<div id="output" class="formdiv">
<input type="text" name="output"/>
</div>
</form>
<script type="text/javascript">
var company;
var jobtitle;
var keywords;
var fname;
var lname;
var notcompany;
var notjobtitle;
var notkeywords;
document.getElementById("onclick").onclick=function() {
company = document.getElementById('cmpy').value;
jobtitle = document.getElementById('jtitle').value;
keywords = document.getElementById('kwrd').value;
fname = document.getElementById('fname').value;
lname = document.getElementById('lname').value;
notcompany = document.getElementById('ncmpy').value;
notjobtitle = document.getElementById('njtitle').value;
notkeywords = document.getElementById('nkwrd').value;
alert(company + jobtitle + keywords + fname + lname + notcompany + notjobtitle + notkeywords);
}
</script>
的用处不大。