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

问题描述 投票:0回答:1

在Haskell Programming From First Principles部分16.13中,Wrap数据类型用于演示一种类型,其Functor实例需要对其中一个参数进行类型类约束:

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

演示了几个不正确的Functor for(Wrap f)实例后,会显示一个正确的实例:

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有足够的信息来推断f在顶部的Wrap定义中的类型(* - > *),所以我无法理解为什么我的尝试不解析。

haskell typeclass functor
1个回答
3
投票

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

我的方法专注于模式匹配,以“没有fmap [...]的”functor-ish“方式使用f

除了语法问题,你不能以这种方式将f用作模式。实例声明中的f是一个类型构造函数,而模式则用于匹配值和值构造函数。最简单的插图,...

id :: x -> x
id x = x

...来自类型签名的x,一个类型变量,与函数定义左侧不同的x,一个匹配值(类型为x)并将它们绑定到变量(名为x)的模式。名称必须重合,没有理由。

如果我理解你的意图,计划是使用(f a)作为一种模式,使f匹配任何“functor-ish”构造函数与内部的某些东西(a)。这不起作用(我们不能以这种方式抽象构造函数),但即使它以某种方式工作,它也不足以完成这项任务。那是因为并非所有的函数值都适合包含其他值的构造函数的模型。一个例子:Nothing :: Maybe Integer。这里没有一元值构造函数,也没有包装任何值。

© www.soinside.com 2019 - 2024. All rights reserved.