类别理论中的函数
Functor 在类别理论中被定义为类别之间的结构保持映射(同态)。具体而言,(所有)对象被映射到对象,并且(所有)箭头被映射到箭头,从而保留了类别定律。
对象是 Haskell 类型和态射的类别是 Haskell 函数,称为 Hask 。因此,从 Hask 到 Hask 的仿函数将包括类型到类型的映射以及从函数到函数的映射。
这个类别理论概念与 Haskell 编程构造 Functor
的关系是相当直接的。从类型到类型的映射采用 f :: * -> *
类型的形式,从函数到函数的映射采用函数 fmap :: (a -> b) -> (f a -> f b)
的形式。把它们放在一起,
class Functor (f :: * -> *) where
fmap :: (a -> b) -> f a -> f b
fmap
是一个操作,它接受一个函数(一种态射),:: a -> b
,并将它映射到另一个函数:: f a -> f b
。假设(但是程序员要确保)Functor
的实例确实是数学仿函数,保留了 Hask 的分类结构:
fmap (id {- :: a -> a -}) == id {- :: f a -> f a -}
fmap (h . g) == fmap h . fmap g
fmap
升降机函数:: a -> b
成的一个子类别 Hask 以保留任何身份箭头两者的存在,和组合物的相关性的方法。
Functor
类只对 Hask 上的 endo 仿函数进行编码。但在数学中,仿函数可以在任意类别之间进行映射。对这个概念的更忠实的编码看起来像这样:
class Category c where
id :: c i i
(.) :: c j k -> c i j -> c i k
class (Category c1, Category c2) => CFunctor c1 c2 f where
cfmap::c1 a b -> c2 (f a) (f b)
标准的 Functor 类是此类的一个特例,其中源类和目标类都是 Hask 。例如,
instance Category (->) where -- Hask
id = \x -> x
f . g = \x -> f (g x)
instance CFunctor (->) (->) [] where
cfmap = fmap