这个类型类约束是必要的还是冗余的?

10
下面的代码成功编译,但在使用GHC 9.2.3和-Wredundant-constraints时会收到警告:
{-# 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 对此持不同意见,所以我不确定。


2
较旧版本的 GHC 实际上不会产生冗余约束警告。(但这并没有真正帮助我们……它仍然看起来像是冗余的。) - leftaroundabout
@leftaroundabout:确实!这个问题基于我在尝试使用更新的 GHC 时开始收到的警告!我不喜欢有警告,但我也不喜欢我的代码无法通过类型检查 :) - yairchu
3
这里显然存在 GHC 的 bug。你可以提交一个工单吗? - dfeuer
1
@dfeuer 好的。鉴于K. A. Buhr的回答,似乎这个错误在警告中而不是在解决/检查中(我不确定哪一个是错误)。我会提交这个错误报告。 - yairchu
1
@dfeuer:已完成,https://gitlab.haskell.org/ghc/ghc/-/issues/21765 - yairchu
1个回答

9
因此,尽管Functor f看起来多余,但它是必需的,以避免递归超类导致包含实际底部(即在隐式访问超类时运行时的无限循环)超类字段的字典问题。

编译器源代码compiler/GHC/Tc/TyCl/Instance.hs中有一段解释,标题为"Recursive superclasses"。总结起来,当解析instance C f的超类Functor f时,GHC不能使用Applicative f来解析Functor f,因为Applicative f不是C f的“较小字典”(见下文)。通过要求超类仅通过越来越小的字典链解决,GHC可以确保超类解析终止。

相比之下,对于这个类似的例子,在实例定义中不需要Functor f
class Functor f => C f x
instance (Applicative f) => C f Int

因为Applicative fC f Int的字典小,所以GHC允许使用它。
这里的“较小的字典”是以特定的技术意义使用的。字典的大小是其类型中构造函数和变量的数量。因此,Applicative f的大小为2,而C f Int的大小为3。
这意味着Functor f实际上并不是多余的,因此警告是错误的。发出警告看起来像是GHC的一个错误。

1
谢谢!根据您的输入,我已经简化了示例,因为我现在明白它与多参数类型类无关。所以我理解类实例上下文需要一些其他上下文不需要的“冗余”,但是目前似乎“-Wredundant-constraints”并没有意识到这一点,对吗? - yairchu

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接