haskell 此类型-类约束是必需的还是多余的?

mwngjboj  于 2022-11-14  发布在  其他
关注(0)|答案(1)|浏览(130)

下列程式码会成功编译,但在搭配-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不同意,所以我不确定。

zf2sa74q

zf2sa74q1#

因此,Functor f看起来是多余的,但它是必要的,以避免递归超类导致包含实际上是底部的超类字段的字典的问题(即,当超类被隐式访问时,在运行时的无限循环)。
在编译器源代码compiler/GHC/Tc/TyCl/Instance.hs中有一个解释,在标题为“递归超类”的部分中。结果是,当为instance C f解析超类Functor f时,不允许GHC使用Applicative f来解析Functor f,因为Applicative f不是“较小的字典”通过要求超类只能通过一系列越来越小的字典来解析,GHC可以确保超类解析终止。
相比之下,在此类似示例的示例定义中不需要Functor f

class Functor f => C f x
instance (Applicative f) => C f Int

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

相关问题