为什么 GHC 不解析 'data Wrap f a = Wrap (f a)' 的仿函数实例?

Why does GHC not parse functor instance for 'data Wrap f a = Wrap (f a)'?

Haskell从第一原则编程第16.13节中,提出了Wrap数据类型来演示其Functor实例的类型需要对其参数之一进行类型类约束:

data Wrap f a =
  Wrap (f a)
  deriving (Eq, Show)

在为 (Wrap f) 演示了几个错误的 Functor 实例之后,显示了一个正确的实例:

instance Functor f => Functor (Wrap f) where
  fmap g (Wrap fa) = Wrap (fmap g fa)

这个类型类实例应该工作的事实对我来说似乎是正确的。确实,GHC毫无怨言地接受了。

为了说服自己 'Functor f' 约束是必需的,我尝试在没有它的情况下创建自己的类型类实例。我的方法侧重于模式匹配,以 "functor-ish" 方式使用 f 而无需 fmap,类似于本书前面所示的方法。这是尝试:

instance Functor (Wrap f) where
  fmap g (Wrap (f a)) = Wrap f (g a)

当我将其加载到 GHCi 中时,出现以下错误:

Prelude> :l 16.12-wrap.hs
[1 of 1] Compiling Main             ( 16.12-wrap.hs, interpreted )

16.12-wrap.hs:10:17: error: Parse error in pattern: f
   |
10 |   fmap g (Wrap (f a)) = Wrap f (g a)
   |                 ^^^
Failed, no modules loaded.

有人可以解释我尝试的实例的问题吗?在我看来,GHC 有足够的信息可以从顶部的 Wrap 定义中推断出 f 属于 (* -> *),所以我不明白为什么我的尝试没有解析。

定义左侧的

fmap g (Wrap (f a)) 会导致解析错误,因为 (f a) 不是语法上有效的模式。

My approach focuses on pattern matching to use f in a "functor-ish" way without fmap [...]

撇开语法问题不谈,您不能按字面意思将 f 用作这种方式的模式。实例声明中的 f 是类型构造函数,而模式是用来匹配值和值构造函数的。对于最小的说明,在...

id :: x -> x
id x = x

... 类型签名中的 x 是一个类型变量,与函数定义左侧的 x 不同,后者是匹配值(类型 x) 并将它们绑定到一个变量(名为 x)。没有理由名称必须一致。

如果我能很好地理解您的意图,计划是使用 (f a) 作为模式,这样 f 就会将任何 "functor-ish" 构造函数与某些东西匹配(a ) 里面。这行不通(我们不能以这种方式对构造函数进行抽象),但即使它以某种方式起作用,也不足以完成这项任务。那是因为并非所有的函子值都符合构造函数包装其他值的模式。一个例子:Nothing :: Maybe Integer。这里没有一元值构造函数,也没有任何值被包装。