为什么 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
。这里没有一元值构造函数,也没有任何值被包装。
在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
。这里没有一元值构造函数,也没有任何值被包装。