【问题标题】:How is "a monoid on applicative functors" different than "a monoid in the category of endofunctors"?“应用函子上的幺半群”与“内函子类别中的幺半群”有何不同?
【发布时间】:2018-10-05 03:19:13
【问题描述】:

也许这些陈述都不是绝对精确的,但单子通常被定义为“内函子类别中的一个幺半群”; Haskell Alternative 被定义为“应用函子上的幺半群”,其中applicative functor 是“强松散的幺半群函子”。现在,这两个定义听起来与无知者(我)非常相似,但效果却大不相同。 Alternative 的中性元素的类型为f a,因此是“空的”,而monad 的类型为a -> m a,因此具有“非空”的含义; Alternative 的操作类型为f a -> f a -> f a,monad 的操作类型为(a -> f b) -> (b -> f c) -> (a -> f c)。在我看来,真正重要的细节是 在 endofunctors 类别中在 endofunctors 类别中,尽管替代方案中的“强松散”细节可能很重要;但这就是我感到困惑的地方,因为至少在 Haskell 中,monad 最终成为了替代品:而且我发现我还没有对这里的所有细节有一个准确的分类理解。

如何准确表达alternative和monad之间的区别,使得它们都是与内函子有关的幺半群,但一个有一个“空”中性元素,另一个有一个“非空”中性元素?

【问题讨论】:

    标签: monads functor applicative category-theory monoids


    【解决方案1】:

    一般来说,幺半群是在幺半群范畴中定义的,这个范畴是定义对象与单位对象的某种(张量)乘积的范畴。

    最重要的是,类型的范畴是幺半群:类型ab的乘积只是(a, b)的对类型,单位类型是()

    然后将幺半群定义为具有两个态射的对象m

    eta :: () -> m
    mu :: (m, m) -> m

    注意eta 只是选择m 的一个元素,所以它等价于mempty,并且柯里化mu 变成了通常的Haskell Monoid 类的mappend

    这是类型和函数的一个类别,但也有一个单独的内函子和自然变换类别。它也是一个幺半群。两个函子的张量积定义为它们的组合Compose f g,单位是恒等函子Id。该类别中的幺半群是单子。和之前一样,我们选择一个对象m,但现在它是一个内函子;和两个态射,现在是自然变换:

    eta :: Id ~> m
    mu :: 编写 m m ~> m

    在组件中,这两种自然变换变成:

    return :: a -> m a
    加入 :: m (m a) -> m a

    应用函子也可以定义为函子类别中的幺半群,但具有更复杂的张量积,称为 Day 卷积。或者,等价地,它可以定义为(松散地)保留单曲面结构的函子。

    Alternative 是类型类别中的幺半群(不是内函子)。该族由应用函子f 生成。对于每个类型a,我们都有一个幺半群,其memptyf a 的一个元素,其mappend 将一对f a 映射到f a 的元素。这些多态函数称为empty<|>

    特别是,empty 必须是多态值,这意味着每个类型 a 都有一个值。例如,对于列表仿函数,这是可能的,其中一个空列表在a 中是多态的,或者对于具有多态值NothingMaybe。请注意,这些都是具有不依赖于类型参数的构造函数的多态数据类型。直觉是,如果您将仿函数视为容器,则此构造函数会创建并清空容器。空容器会自动多态。

    【讨论】:

      【解决方案2】:

      这两个概念都与“monoidal category”的概念相关,您可以在该类别中定义幺半群的概念(以及某些其他类型的代数结构)。您可以将 monoidal 类别视为: category 定义了一个参数的函数的抽象概念; monoidal category 定义了零参数或多个参数的函数的抽象概念。

      单子是内函子范畴中的一个幺半群;换句话说,它是一个幺半群,其中乘积(2 个参数的函数)和恒等式(0 个参数的函数)使用由特定(奇异)单群类别(内函子的单群类别)定义的多参数函数的概念和组成)。

      applicative functor 是 monoidal functor。换句话说,它是一个函子,它保留了一个幺半群类别的所有结构,而不仅仅是使它成为一个类别的部分。很明显,这意味着它具有用于具有任意数量参数的函数的 mapN 函数,而不仅仅是一个参数的函数(就像普通函子一样)。

      所以一个单子存在一个特定的幺半群类别(恰好是一个内函子的范畴),而一个应用函子映射两个幺半群类别(恰好是属于同一范畴,因此是一种内函子)。

      【讨论】:

        【解决方案3】:

        为了用一些 Haskell 代码补充其他答案,下面是我们如何表示 @Bartosz Milewski 所指的 Day 卷积幺半群结构:

        data Day f g a = forall x y. Day (x -> y -> a) (f x) (g y)
        

        单位对象是函子Identity

        然后我们可以将应用类重新构造为相对于这个幺半群结构的幺半群对象:

        type f ~> g = forall x. f x -> g x
        class Functor f => Applicative' f
          where
          dappend :: Day f f ~> f
          dempty :: Identity ~> f
        

        您可能会注意到这与其他熟悉的幺半群对象是如何押韵的,例如:

        class Functor f => Monad f
          where
          join :: Compose f f ~> f
          return :: Identity ~> f
        

        或:

        class Monoid m
          where
          mappend :: (,) m m -> m
          mempty :: () -> m
        

        稍稍眯起眼睛,您可能还可以看到dappend 只是liftA2 的包装版本,同样demptypure

        【讨论】:

          猜你喜欢
          • 2014-06-12
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-04-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多