范畴论 POV 中的 Applicative Functor 定义是什么?
What is Applicative Functor definition from the category theory POV?
我能够通过以下方式将函子的定义从范畴论映射到 Haskell 的定义:由于 Hask
的对象是类型,函子 F
- 将
Hask
的每个类型 a
映射到新类型 F a
,粗略地说,在其前面加上 "F "。
- 使用
fmap :: (a -> b) -> (f a -> f b)
. 将 Hask
的每个态射 a -> b
映射到新的态射 F a -> F b
到目前为止,还不错。现在我到了Applicative
,在教科书中找不到任何提及这样一个概念的地方。通过查看它添加到 Functor
、ap :: f (a -> b) -> f a -> f b
的内容,我试图得出自己的定义。
首先,我注意到由于 (->)
也是一种类型,所以 Hask
的态射也是它的对象。鉴于此,我建议应用函子是一个函子,它也可以将 "arrow"-源类别的对象映射到目标类别的态射。
这是正确的直觉吗?你能提供一个更正式、更严谨的定义吗?
你说得对,Applicative
的翻译不如 Functor
或 Monad
直截了当。但本质上是monoidal functors的class:
class Functor f => Monoidal f where
pureUnit :: f ()
fzip :: f a -> f b -> f (a,b)
从那里你可以定义 – 在 Hask –
pure x = fmap (const x) pureUnit
和
fs <*> xs = fmap (uncurry ($)) $ fzip fs xs
请参阅 以获得 Applicative
和 Monoidal
真正等价的完整证明。
理解应用函子的关键是弄清楚它们保留的结构。
常规函子保留了基本的分类结构:它们在类别之间映射对象和态射,并且保留了类别的法则(结合性和恒等性)。
但是一个类别可能有更多的结构。例如,它可能允许定义类似于态射但采用多个参数的映射。这种映射是通过柯里化定义的:例如,两个参数的函数被定义为一个参数返回另一个函数的函数。如果您可以定义一个表示函数类型的对象,这是可能的。一般来说,这个对象被称为指数(在Haskell中,它只是b->c
类型)。然后我们可以得到从一个对象到指数的态射,并将其称为 two-argument 态射。
Haskell 中应用函子的传统定义是基于多参数映射函数的思想。但是有一个等效的定义将 multi-argument 函数沿不同的边界拆分。您可以将这样的函数视为 product(一对,在 Haskell 中)到另一种类型(此处为 c
)的映射。
a -> (b -> c) ~ (a, b) -> c
这使我们能够将应用函子视为保留乘积的函子。但是产品只是所谓的幺半群结构的一个例子。
一般来说,幺半群范畴是指具备张量积和单位对象的范畴。例如,在 Haskell 中,这可能是笛卡尔积(一对)和单位类型 ()
。但是请注意,幺半群法则(结合律和单位法则)仅在同构时有效。例如:
(a, ()) ~ a
然后可以将应用函子定义为保留幺半群结构的函子。特别是,它应该保存单位和产品。我们在应用仿函数之前还是之后执行 "multiplication" 应该无关紧要。结果应该是同构的。
然而,我们并不真的需要 full-blown 幺半群仿函数。我们所需要的只是两种态射(与同构相对)——一种用于乘法,一种用于单位。这样一个 half-preserves 幺半群结构的函子称为 松弛幺半群函子 。因此替代定义:
class Functor f => Monoidal f where
unit :: f ()
(**) :: f a -> f b -> f (a, b)
很容易证明 Monoidal
等价于 Applicative
。例如,我们可以从 unit
得到 pure
,反之亦然:
pure x = fmap (const x) unit
unit = pure ()
应用法则简单地遵循幺半群法则(结合律和单位法则)。
在范畴论中,幺半群结构的保持与张量强度有关,因此应用函子也称为强松弛幺半群函子.但是,在 Hask 中,每个函子都具有关于乘积的规范强度,因此这个 属性 不会对定义添加任何内容。
现在,如果您熟悉将 monad 定义为内函子类别中的幺半群,您可能有兴趣知道应用程序同样是内函子类别中的幺半群,其中张量积是日卷积。但这更难解释。
我能够通过以下方式将函子的定义从范畴论映射到 Haskell 的定义:由于 Hask
的对象是类型,函子 F
- 将
Hask
的每个类型a
映射到新类型F a
,粗略地说,在其前面加上 "F "。 - 使用
fmap :: (a -> b) -> (f a -> f b)
. 将
Hask
的每个态射 a -> b
映射到新的态射 F a -> F b
到目前为止,还不错。现在我到了Applicative
,在教科书中找不到任何提及这样一个概念的地方。通过查看它添加到 Functor
、ap :: f (a -> b) -> f a -> f b
的内容,我试图得出自己的定义。
首先,我注意到由于 (->)
也是一种类型,所以 Hask
的态射也是它的对象。鉴于此,我建议应用函子是一个函子,它也可以将 "arrow"-源类别的对象映射到目标类别的态射。
这是正确的直觉吗?你能提供一个更正式、更严谨的定义吗?
你说得对,Applicative
的翻译不如 Functor
或 Monad
直截了当。但本质上是monoidal functors的class:
class Functor f => Monoidal f where
pureUnit :: f ()
fzip :: f a -> f b -> f (a,b)
从那里你可以定义 – 在 Hask –
pure x = fmap (const x) pureUnit
和
fs <*> xs = fmap (uncurry ($)) $ fzip fs xs
请参阅 Applicative
和 Monoidal
真正等价的完整证明。
理解应用函子的关键是弄清楚它们保留的结构。
常规函子保留了基本的分类结构:它们在类别之间映射对象和态射,并且保留了类别的法则(结合性和恒等性)。
但是一个类别可能有更多的结构。例如,它可能允许定义类似于态射但采用多个参数的映射。这种映射是通过柯里化定义的:例如,两个参数的函数被定义为一个参数返回另一个函数的函数。如果您可以定义一个表示函数类型的对象,这是可能的。一般来说,这个对象被称为指数(在Haskell中,它只是b->c
类型)。然后我们可以得到从一个对象到指数的态射,并将其称为 two-argument 态射。
Haskell 中应用函子的传统定义是基于多参数映射函数的思想。但是有一个等效的定义将 multi-argument 函数沿不同的边界拆分。您可以将这样的函数视为 product(一对,在 Haskell 中)到另一种类型(此处为 c
)的映射。
a -> (b -> c) ~ (a, b) -> c
这使我们能够将应用函子视为保留乘积的函子。但是产品只是所谓的幺半群结构的一个例子。
一般来说,幺半群范畴是指具备张量积和单位对象的范畴。例如,在 Haskell 中,这可能是笛卡尔积(一对)和单位类型 ()
。但是请注意,幺半群法则(结合律和单位法则)仅在同构时有效。例如:
(a, ()) ~ a
然后可以将应用函子定义为保留幺半群结构的函子。特别是,它应该保存单位和产品。我们在应用仿函数之前还是之后执行 "multiplication" 应该无关紧要。结果应该是同构的。
然而,我们并不真的需要 full-blown 幺半群仿函数。我们所需要的只是两种态射(与同构相对)——一种用于乘法,一种用于单位。这样一个 half-preserves 幺半群结构的函子称为 松弛幺半群函子 。因此替代定义:
class Functor f => Monoidal f where
unit :: f ()
(**) :: f a -> f b -> f (a, b)
很容易证明 Monoidal
等价于 Applicative
。例如,我们可以从 unit
得到 pure
,反之亦然:
pure x = fmap (const x) unit
unit = pure ()
应用法则简单地遵循幺半群法则(结合律和单位法则)。
在范畴论中,幺半群结构的保持与张量强度有关,因此应用函子也称为强松弛幺半群函子.但是,在 Hask 中,每个函子都具有关于乘积的规范强度,因此这个 属性 不会对定义添加任何内容。
现在,如果您熟悉将 monad 定义为内函子类别中的幺半群,您可能有兴趣知道应用程序同样是内函子类别中的幺半群,其中张量积是日卷积。但这更难解释。