GHC是否允许newtype包含存在类型变量?编译与检查矛盾咨询
问题解答
首先明确:你遇到的情况是合法的,GHC手册的描述和aeson中的newtype定义并不冲突,flycheck的报错属于误判。
1. GHC手册禁止的是什么?
GHC手册《6.4.6 Existentially quantified data constructors》里提到的"You can’t use existential quantification for newtype declarations.",针对的是newtype构造器本身携带存在量化的类型变量,比如这种写法是绝对禁止的:
-- 非法:newtype构造器使用存在量化 newtype Bad = Bad (forall a. a) -- GHC中forall在参数位置默认是存在量化语义
或者更明确的存在量化写法:
-- 同样非法 newtype Bad = forall a. Bad a
2. aeson中的定义为什么合法?
aeson的Parser newtype定义里的forall f r. ...,是字段runParser的类型为rank-2多态函数,属于rank-n类型的范畴,不是存在量化。这种写法在开启RankNTypes(或Rank2Types)扩展后是完全合法的,GHC从很早的版本就支持这种用法。
简单说:手册禁止的是newtype构造器本身带存在量化变量,而这里是newtype的字段拥有一个多态类型,两者是完全不同的概念。
3. flycheck报错的原因
flycheck的静态检查规则可能没有准确区分存在量化和rank-n类型,误把字段中的forall判定为存在量化,从而抛出错误。但你本地用GHC 9.6.6编译通过,说明GHC本身是认可这个写法的,实际编译没有问题。
内容的提问来源于stack exchange,提问作者Jason Whittle
相关产品推荐
相关产品推荐

