haskell - 为什么 GHC 不解析 'data Wrap fa = Wrap (fa)' 的函子实例?
问题描述
在Haskell Programming From First Principles第 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”约束,我尝试在没有它的情况下创建自己的类型类实例。我的方法侧重于模式匹配,在没有 fmap 的情况下以“仿函数”的方式使用 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 是一种 (* -> *),所以我不明白为什么我的尝试没有解析。
解决方案
fmap g (Wrap (f a))
在定义的左侧会导致解析错误,因为(f a)
它不是语法上有效的模式。
我的方法侧重于模式匹配,以在没有 fmap 的情况下以“仿函数”的方式使用 f [...]
撇开语法问题不谈,您不能f
以这种方式将其用作模式。实例声明中的f
是类型构造函数,而模式旨在匹配值和值构造函数。对于一个最小的说明,在...
id :: x -> x
id x = x
...x
来自类型签名的类型变量x
与函数定义的左侧不同,后者是匹配值(类型x
)并将它们绑定到变量(命名x
)的模式。没有理由名称必须一致。
如果我很好地理解了您的意图,那么计划是(f a)
用作一种模式,以便f
将任何“仿函数”构造函数与a
内部的某些东西 (the) 匹配。这不起作用(我们不能以这种方式抽象构造函数),但即使它确实以某种方式起作用,它也不足以完成这项任务。这是因为并非所有的函数值都适合包装其他值的构造函数的模式。一个例子:Nothing :: Maybe Integer
。这里没有一元值构造函数,也没有任何值被包装。
推荐阅读
- ssis - Excel 停止刷新 Olap 多维数据集
- java - Android是否可以在没有dx的情况下加载jar?
- azerothcore - 重生后玩家看不见的生物
- javascript - 如何通过 instafeed.js 插件在我们的网站中显示 instagram 的标题部分
- arrays - 从 pyspark 数据框列创建结构数组
- javascript - 无法使用 http 删除/放置请求删除或编辑项目
- java - 有没有办法根据日志的内容更改日志的级别?
- windows - 无法使用 VSCode/GoLand 在 Windows 上调试 Go 代码(获取“%1 不是有效的 Win32 应用程序”)
- c# - 格式化小数以删除尾随零并使用千分位分隔符
- java - 运行自动化脚本时登录会话过期