You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何a→a不是函子?关于Bartosz文章相关论断的疑问

为什么你的fmap定义不构成合法函子?

你提到的这个构造——把类型a映射到a -> a,并定义fmap f aa = id——乍一看好像满足复合律,但其实它违反了函子的核心要求之一:恒等律,而且从范畴论的本质定义来看,它也没有正确保持范畴的结构。下面具体拆解:

1. 直接违反函子的恒等律

函子的第一个硬性规则是:对于任意对象a,fmap id必须是作用在F a上的恒等态射。换句话说,不管你传入什么x :: F a,fmap id x必须原封不动地返回x本身。

看你的定义:

fmap :: (a -> b) -> (a -> a) -> (b -> b)
fmap f aa = id

当f是id :: a -> a时,fmap id aa = id。但这里的问题非常明显:返回的id函数(比如\x -> x)根本不是你传入的aa啊!举个例子,如果aa是\x -> x + 1(一个Int -> Int的函数),那fmap id aa返回的是\x -> x,而不是原来的加1函数——这直接违反了恒等律,fmap id没有起到“恒等映射”的作用。

2. 范畴论层面的本质缺陷

从范畴论的角度说,函子是两个范畴之间的结构保持映射,它需要做到两点:

  • 映射对象:把源范畴的每个对象a映射到目标范畴的对象(你把a映射到a -> a,这部分没问题);
  • 映射态射:把源范畴的每个态射h :: a -> b映射到目标范畴的态射F h :: F a -> F b,并且必须保持恒等态射和态射的复合:
    • 源范畴的恒等态射id_a,被映射后必须是目标范畴中F a上的恒等态射(也就是id :: (a -> a) -> (a -> a),即输入什么函数就返回什么函数);
    • 源范畴中两个态射的复合g . f,被映射后必须等于两个映射态射的复合F g . F f。

你的定义里,F id_a是一个总是返回id函数的函数,而不是目标范畴的恒等态射——这就彻底破坏了范畴结构的保持。函子的核心意义就是“不改变结构地转换范畴”,你这里把恒等态射映射成了一个完全无关的态射,自然不可能被认可为函子。

补充:为什么复合律看起来成立?

你可能已经注意到,你的定义里fmap (g . f) aa = id,而(fmap g . fmap f) aa = fmap g id = id,看起来复合律是满足的。但要记住:复合律成立只是必要条件,不是充分条件——函子必须同时满足恒等律和复合律,缺一不可。只满足复合律的映射,根本算不上函子。

内容的提问来源于stack exchange,提问作者allidoiswin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 08:50:50