为什么GHC不能为'data Wrap f a = Wrap(f a)'解析函子实例?

时间:2019-04-09 01:53:04

标签: haskell typeclass functor

从第一原理开始的Haskell编程部分中,给出了 Wrap 数据类型,以演示其Functor实例对其参数之一要求类型限制的类型:

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

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

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

这个类型类实例应该工作的事实在我看来是正确的。确实,GHC毫无保留地接受了它。

为了使自己确信需要'Functor f'约束,我尝试在没有该约束的情况下创建自己的类型类实例。我的方法着重于模式匹配,以在没有fmap的情况下以“ functor-ish”方式使用f,类似于本书前面所展示的方法。这是尝试:

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是(*-> *)类型,所以我不明白为什么我的尝试无法解析。

1 个答案:

答案 0 :(得分:3)

定义左侧的

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

  

我的方法着重于模式匹配,以“ functor-ish”方式使用f而不使用fmap [...]

除了语法问题,您不能以这种方式从字面上使用f作为模式。实例声明中的f是类型构造函数,而模式则用于匹配值和值构造函数。为简单起见,请在...

id :: x -> x
id x = x

...类型签名中的x(类型变量)与函数定义左侧的x不同,该模式与值({{1 }})并将其绑定到变量(名为x)。名称没有理由必须重合。

如果我能很好地理解您的意图,则计划使用x作为一种模式,以使(f a)与内部任何东西(f)匹配的“ functor-ish”构造函数。那是行不通的(我们不能以这种方式对构造函数进行抽象),但是即使它以某种方式起作用了,也不能胜任这项任务。这是因为并非所有函数值都适合包装其他值的构造函数。一个示例:a。这里没有一元值构造函数,也没有包装任何值。