下列程式码会成功编译,但在搭配-Wredundant-constraints
使用GHC 9.2.3时会收到警告:
{-# LANGUAGE UndecidableInstances, FlexibleInstances #-}
class Functor f => C f where c :: f Int
instance (Functor f, Applicative f) => C f where c = pure 42
由此产生的警告:
test.hs:5:10: warning: [-Wredundant-constraints]
• Redundant constraint: Functor f
• In the instance declaration for ‘C f’
|
5 | instance (Functor f, Applicative f) => C f where c = pure 42
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
但是,如果删除此约束,代码将不再进行类型检查:
test.hs:5:10: error:
• Could not deduce (Functor f)
arising from the superclasses of an instance declaration
from the context: Applicative f
bound by the instance declaration at test.hs:5:10-29
Possible fix:
add (Functor f) to the context of the instance declaration
• In the instance declaration for ‘C f’
|
5 | instance Applicative f => C f where c = pure 42
| ^^^^^^^^^^^^^^^^^^^^
这让我很困惑。
这种约束是真的多余,还是事实上是必要的?
直觉上,我会说这是多余的,因为它已经被Applicative f
所暗示了!但是GHC不同意,所以我不确定。
1条答案
按热度按时间zf2sa74q1#
因此,
Functor f
看起来是多余的,但它是必要的,以避免递归超类导致包含实际上是底部的超类字段的字典的问题(即,当超类被隐式访问时,在运行时的无限循环)。在编译器源代码
compiler/GHC/Tc/TyCl/Instance.hs
中有一个解释,在标题为“递归超类”的部分中。结果是,当为instance C f
解析超类Functor f
时,不允许GHC使用Applicative f
来解析Functor f
,因为Applicative f
不是“较小的字典”通过要求超类只能通过一系列越来越小的字典来解析,GHC可以确保超类解析终止。相比之下,在此类似示例的示例定义中不需要
Functor f
:因为
Applicative f
是比C f Int
小的字典,所以允许GHC使用它。这里使用的“较小字典”是一种特殊的技术含义。字典的大小是其类型中构造函数和变量的数量。因此,
Applicative f
的大小是2,而C f Int
的大小是3。这意味着
Functor f
* 实际上并不是 * 冗余的,所以这个警告是错误的。发出这个警告看起来像是一个GHC bug。