“Functor是一个将对象和态射进行映射的函数,它保留了范畴的组合性和恒等性。”
那么我们先来定义一下什么是范畴?
它是一堆对象!
在一个圆圈里画几个点(现在只有两个点,一个是‘a’,另一个是‘b’),然后给这个圆圈起个名字叫做A(Category)。
那么范畴都包含哪些内容呢?
对象之间的组合以及每个对象的恒等函数。
因此,在应用Functor之后,我们需要映射这些对象并保留其组合性。
让我们想象一下,‘A’是我们的范畴,其中有对象['a', 'b'],并且存在一个态射a -> b。
现在,我们需要定义一个能够将这些对象和态射映射到另一个范畴'B'的Functor。
假设这个Functor叫做'Maybe'。
data Maybe a = Nothing | Just a
所以,类别'B'看起来像这样。
请再画一个圆圈,这次用'Maybe a'和'Maybe b'代替'a'和'b'。
一切似乎都很好,所有对象都被映射了。
'a'变成了'Maybe a','b'变成了'Maybe b'。
但问题是我们还必须映射从'a'到'b'的态射。
这意味着'A'中的态射a -> b应该映射到'Maybe a' -> 'Maybe b'的态射。
a -> b的态射称为f,则'Maybe a' -> 'Maybe b'的态射称为'fmap f'。
现在让我们看看函数'f'在'A'中是如何工作的,并看看我们是否可以在'B'中复制它。
'A'中'f'的函数定义:
f :: a -> b
f接受a并返回b
在'B'中,'f'的函数定义为:
f :: Maybe a -> Maybe b
f接受一个Maybe a类型的参数,并返回一个Maybe b类型的结果
让我们看看如何使用fmap将函数'f'从'A'映射到'B'中的'fmap f'函数
fmap的定义
fmap :: (a -> b) -> (Maybe a -> Maybe b)
fmap f Nothing = Nothing
fmap f (Just x) = Just(f x)
那么,我们在做什么呢?
我们正在将函数 'f' 应用于类型为 'a' 的 'x'。'Nothing' 的特殊模式匹配来自 Functor Maybe
的定义。
所以,我们将我们的对象 [a, b] 和态射 [ f ] 从范畴 'A' 映射到范畴 'B'。
这就是 Functor!
fmap
映射了函数。涉及到两种不同的映射方式,这种思考方式将有助于理解范畴论(更为一般化)。我的意思是,了解基本的范畴论有助于我们理解Haskell中的所有范畴论知识(如函数子、单子等),这很有趣。 - Ludovic Kuty