This answer from a Category Theory perspective包含以下语句:
...事实是,协函子和逆函子之间并没有真正的区别,因为每个函子都只是协变函子。
...
更多详细信息,从类别C到类别D的逆变函子F无非是F:C op →D类型的(协变)函子,从C的相反类别到D。 D类。
另一方面,Haskell的Functor
和Contravariant
仅分别需要为实例定义fmap
和contramap
。这表明从Haskell的角度来看,存在的对象是Contravariant
但不是Functor
(反之亦然)。
因此,似乎在分类论中“协函子和反函子之间没有真正的区别”,而在Haskell中,Contravariant
和Functor
之间有区别。
我怀疑这种差异与Haskell中在Hask中实现的所有实现都有关系,但我不确定。
我想我自己理解了类别理论和Haskell的每种观点,但是我正在努力寻找一种将两者联系起来的直觉。
答案 0 :(得分:9)
为了方便。
可以通过more general Functor
类来解决,并为Hask上的endofunctors定义实例(对应于我们现有的Functor
),并定义从Hask ^ op到Hask的函子(对应于我们现有的{{1 }})。但这要付出比喻性的认知成本和相当大的语法成本:然后必须依靠类型推断或类型注释来选择实例,并且存在显式转换(在命名空间中名为Contravariant
和Op
标准库)进出Hask ^ op。
使用名称getOp
和fmap
降低了这两个成本:读者不必费心地运行Hindley-Milner来确定在确定实例时选择的实例,而编写者则不需要在存在歧义的情况下进行显式转换或类型注释以选择实例。
(我实际上是在这里重写历史。 real 的原因是因为语言设计人员认为专门的contramap
会很有用,并且没有想像或没有看到需要更通用的Functor
。人们后来才发现它有时是有用的,但是使用广义Functor
类的经验表明这可能很乏味,而最常见的专门类出于上述原因,这些案例毕竟是出乎意料的好选择。)
答案 1 :(得分:6)
从数学上来说,将反函子视为函子的类的不同只是一种符号上的方便;对变函子F : C -> D
总是可以定义为协变函子F' : C^{op} -> D
,因此,摆脱对函函子的想法只会迫使您明确地谈论相反的范畴。
在Haskell中,Functor
类表示(假定)类别 Has 上的endofunctor。没有简便的方法可以直接表示 HASK OP (或者至少不能以一种有助于我们从该类别定义函子的形式),也没有类型类可以定义exofunctor *,因此我们定义一个Contrafunctor
类,其contramap
函数可以使 Hask “按需”箭头反向,可以这么说。
*“ exofunctor”是真实名词吗?我只是把它表示为不是endofunctor的函子。
答案 2 :(得分:5)
想象一下,我们遇到了类似以下的事情。
class MoreAccurateFunctor c d f where
fmap :: c a b -> d (f a) (f b)
由于(->)
是Category
的实例(这是 Hask ),因此我们将拥有Functor ~ MoreAccurateFunctor (->) (->)
。
现在,假设我们有Dual (->)
,是(->)
的双重类别(这将是 Hask Op ,而我们将有{{1 }}),我们将拥有Dual (->) a b ~ (b -> a)
。
我不知道这是否有帮助,但想法是指出Contravariant ~ MoreAccurateFunctor (Dual (->)) (->)
和Functor
是Contravariant
的两个专业化事实,而后一类更接近于定义类理论中的函子。