【问题标题】:What is Applicative Functor definition from the category theory POV?范畴论 POV 中的 Applicative Functor 定义是什么?
【发布时间】:2016-01-26 11:54:30
【问题描述】:

我能够通过以下方式将 Functor 的定义从范畴论映射到 Haskell 的定义:因为 Hask 的对象是类型,所以 functor F

  • Hask 中的每个类型a 映射到新类型F a,粗略地说,在它前面加上“F”。
  • 使用fmap :: (a -> b) -> (f a -> f b)Hask的每个态射a -> b映射到新的态射F a -> F b

到目前为止,一切都很好。现在我到Applicative,在教科书中找不到任何提到这样一个概念的地方。通过查看它对Functorap :: f (a -> b) -> f a -> f b 添加的内容,我试图提出自己的定义。

首先,我注意到由于(->) 也是一个类型,Hask 的态射也是它的对象。鉴于此,我提出应用函子是一种函子,它也可以将源类别的“箭头”对象映射到目标类别的态射。

这是正确的直觉吗?你能提供一个更正式、更严格的定义吗?

【问题讨论】:

标签: haskell applicative category-theory


【解决方案1】:

理解应用函子的关键是弄清楚它们保留什么结构。

正则函子保留了基本的分类结构:它们映射类别之间的对象和态射,并且它们保留了类别的规律(关联性和同一性)。

但是一个类别可能有更多的结构。例如,它可能允许定义类似于态射但采用多个参数的映射。这种映射是通过柯里化定义的:例如,两个参数的函数被定义为一个参数返回另一个函数的函数。如果您可以定义一个表示函数类型的对象,这是可能的。通常,这个对象被称为指数对象(在 Haskell 中,它只是类型b->c)。然后我们可以有从一个对象到指数的态射,并将其称为双参数态射。

Haskell 中应用函子的传统定义是基于多个参数的映射函数的思想。但是有一个等价的定义可以将多参数函数沿不同的边界分割。您可以将这样的函数视为 product(Haskell 中的一对)到另一种类型(此处为 c)的映射。

a -> (b -> c)  ~  (a, b) -> c

这使我们可以将应用函子视为保留产品的函子。但产品只是所谓的单曲面结构的一个例子。

一般来说,幺半群类别是配备张量积和单位对象的类别。例如,在 Haskell 中,这可能是笛卡尔积(一对)和单位类型 ()。但是请注意,单曲面定律(结合律和单位定律)仅在同构之前有效。例如:

(a, ())  ~  a

然后可以将应用函子定义为保留单曲面结构的函子。特别是,它应该保护单位和产品。我们是否在应用函子之前或之后进行“乘法”并不重要。结果应该是同构的。

然而,我们并不真正需要一个成熟的幺半群函子。我们所需要的只是两个态射(与同构相反)——一个用于乘法,一个用于单位。这种半保留幺半体结构的函子称为松散的幺半体函子。因此,替代定义:

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 定义为内函子类别中的幺半群,您可能有兴趣知道应用程序同样是内函子类别中的幺半群,其中张量积是 Day卷积。但这很难解释。

【讨论】:

  • 这是什么“力量”的东西?
  • 是的,如果您可以在此处添加一些“强度”的含义,那就更清楚了;特别是因为leftaroundabout的答案链接到@ 987654321@,它似乎将“强幺半群仿函数”定义为“假设了一些约束的单曲面仿函数”,而“松散幺半群仿函数”表示“没有额外的假设”,所以在那个术语中“强松散幺半群”函子”似乎没有意义。
  • 我个人更喜欢将应用函子视为“封闭函子”而不是单曲面函子。它们是幺半群的事实或多或少是巧合,并且是由指数的保留所迫使的,这就是为什么事物的“单群”编码感觉如此混乱的原因,而我们使用的(<*>) :: f (a -> b) -> f a -> f b 组合器正是指数的映射!考虑 Applicative 的另一种方式是作为一个关于(协变)Day 卷积的幺半群对象。这种观点的好处是它阐明了寻找 Applicative 逆变形式的途径。
  • 当我在精神上将(**) 转换为(f a, f b) -> f (a, b) 时,这对我来说更有意义。我想知道你为什么不一开始就这样写。
  • @arrowd:事实上,一个甚至可能“更深”的变体是((a,b)->c) -> (f a,f b)->f c,这反映了函子将一个类别的幺半体结构转换为另一个类别的结构(尽管这两个类别都是 Hask 这里)。
【解决方案2】:

你说得对,Applicative 的翻译不如FunctorMonad 直截了当。但本质上是monoidal functors的类:

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

请参阅 this answer 以了解 ApplicativeMonoidal 确实等效的完整证明。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-06-30
    • 2012-01-29
    • 2011-11-05
    • 2017-04-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多