范畴论是现代数学理论,是抽象代数的分支,专注于联系和关系的本质。它对于为许多高度可重用的编程抽象提供坚实的基础和通用语言很有用。Haskell使用类别理论作为标准库和一些流行的第三方库中可用的一些核心类型的灵感。
该Functor类型类的说,如果一个类F实例化Functor(为我们写的Functor F),那么我们有一个通用的操作
fmap :: (a -> b) -> (F a -> F b)
这使我们可以“映射” F。标准的(但不完美的)直觉是F a一个充满类型值的容器a,fmap让我们对每个包含的元素进行转换。一个例子是Maybe
instance Functor Maybe where fmap f Nothing = Nothing -- if there are no values contained, do nothing fmap f (Just a) = Just (f a) -- else, apply our transformation
在这种直觉下,一个常见的问题是“为什么不叫Functor类似的东西Mappable?”。
原因是Functor符合类别理论中的一组常见结构,因此通过调用Functor“ Functor”,我们可以看到它如何与这种更深层次的知识联系起来。
特别地,类别理论高度关注从一个地方到另一个地方的箭头的想法。在Haskell中,最重要的箭头集是功能箭头a -> b。在类别理论中研究的一个共同点是一组箭头与另一组箭头之间的关系。特别是对于任何类型的构造函数F,形状的箭头集F a -> F b也很有趣。
因此,Functor可以F使普通的Haskell箭头a -> b和F-specific箭头之间具有联系F a -> F b。连接由定义fmap,我们也认识到一些必须遵守的法律
forall (x :: F a) . fmap id x == x forall (f :: a -> b) (g :: b -> c) . fmap g . fmap f = fmap (g . f)
所有这些定律都是自然地从“类别理论”的解释中产生的Functor,如果我们仅将其Functor视为与“元素映射”有关,则显然没有必要。