在Haskell中,类
在范畴论中,双函子是根据ncatlab的定义,"简单地指一个定义域为积范畴的函子:对于C1、C2和D三个范畴,从C1和C2到D的函子F:C1×C2⟶D被称为从C1和C2到D的双函子。"
现在如果我要实现这个范畴定义,我会写下以下内容:
特别是,
现在更进一步,自从
这个量化约束告诉我们,一个双函子是一个“在其第二个参数中”的函子,这显然与范畴定义不符。
我理解,从类“Bifunctor”中,可以得到“一些”双函子,其中第一个和第二个参数的类型不相互作用,但不是“所有”的双函子。实际上,我甚至可以说类“Bifunctor”实现了两个函子的“乘积”,而不是一个真正的双函子。
所以我的问题是:我是否误解了什么?还是Haskell中的双函子实际上并不是双函子?类“MyBifunctor”有意义吗?
Bifunctor
的定义如下:class Bifunctor p where
bimap :: (a -> b) -> (c -> d) -> p a c -> p b d
在范畴论中,双函子是根据ncatlab的定义,"简单地指一个定义域为积范畴的函子:对于C1、C2和D三个范畴,从C1和C2到D的函子F:C1×C2⟶D被称为从C1和C2到D的双函子。"
现在如果我要实现这个范畴定义,我会写下以下内容:
class MyBifunctor p where
myBimap :: ((a,c) -> (b,d)) -> p a c -> p b d
特别是,
myBimap
看起来很像fmap
,这是我认为我们想要的,因为双函子就是一个函子。现在更进一步,自从
base 4.18.0
以来,添加了一个量化约束:class (forall a. Functor (p a)) => Bifunctor p where
bimap :: (a -> b) -> (c -> d) -> p a c -> p b d
这个量化约束告诉我们,一个双函子是一个“在其第二个参数中”的函子,这显然与范畴定义不符。
我理解,从类“Bifunctor”中,可以得到“一些”双函子,其中第一个和第二个参数的类型不相互作用,但不是“所有”的双函子。实际上,我甚至可以说类“Bifunctor”实现了两个函子的“乘积”,而不是一个真正的双函子。
所以我的问题是:我是否误解了什么?还是Haskell中的双函子实际上并不是双函子?类“MyBifunctor”有意义吗?
MyBifunctor
只是对Functor
在对偶对上的函数的限制,这更符合范畴论中的定义,但对我来说似乎并没有立即的实用性。 - undefined(a,c) -> (b,d)
这部分——在乘积范畴中,这不是一个态射,因为它应该是(大致上)(a->b, c->d)
。问题在于Haskell的表示方式具有误导性:在Haskell中,(a,b)
表示的是乘积对象a
乘以b
,而不是对象对(乘积范畴中的对象)。 - undefinedBifunctor
只处理形式为p :: Hask * Hask -> Hask
(柯里化)的函子,其中"Hask"是Haskell类型所在的虚构类别。毕竟,Functor
类也只处理Hask->Hask的函子。也许可以尝试更通用的方法,使用类似Control.Category.Category
的东西,并在那里定义(双)函子。也许在Hackage上的某个包中已经完成了这个(?) - undefined