Scala Cats-Laws中函子复合律为何与标准定义存在差异?
协变函子复合律:Cats实现与你的版本差异解析
首先明确结论:Cats-laws中的版本是正确的,你的翻译版本存在概念混淆。
1. 数学定义的正确映射
函子复合律的标准数学表述是:F(g∘f) = F(g)∘F(f),其中:
f: A→B,g: B→C是集合范畴中的态射(函数)F(f): F[A]→F[B]是函子F作用在f上得到的态射(即Scala中的map(f),它是一个从F[A]到F[B]的函数)∘表示态射的复合:F(g)∘F(f)的含义是“先应用F(f),再应用F(g)”
对应到Scala的具体值操作上:
F(g)∘F(f)作用于fa: F[A],就是F(g)(F(f)(fa)),也就是先对fa调用map(f)得到F[B],再对这个结果调用map(g),即fa.map(f).map(g)F(g∘f)作用于fa,就是fa.map(f.andThen(g))(因为f.andThen(g)就是g∘f的Scala写法)
这正是Cats-laws中实现的逻辑,完全贴合数学定义。
2. 你的版本错误原因
你写的fa.map(f).andThen(fa.map(g))存在两个关键问题:
fa.map(f)的结果是F[B]类型的值,而不是函数,Scala中普通函子的F[B]并没有andThen方法(andThen是函数类型A=>B的方法)- 即便强行假设这里的
andThen是函数复合,fa.map(g)是F[A]→F[C]的函数,和fa.map(f)(F[A]→F[B])的类型也无法复合,逻辑上完全不成立
你混淆了“函子作用在态射上的复合”和“对函子值的操作”,才会写出这个错误版本。
3. Haskell版本的贴合度
Haskell中函子复合律的定义是:fmap (g . f) = fmap g . fmap f
- 这里的
.是Haskell的函数复合运算符,fmap g . fmap f表示“先执行fmap f,再执行fmap g” - 对应到值的操作就是
fmap g (fmap f fa),和Scala中fa.map(f).map(g)完全等价,因此Haskell的实现和Cats一样,都是严格贴合标准数学定义的。
内容的提问来源于stack exchange,提问作者tribbloid
相关产品推荐
相关产品推荐

