"a monoid on applicative functors" 与 "a monoid in the category of endofunctors" 有何不同?
How is "a monoid on applicative functors" different than "a monoid in the category of endofunctors"?
也许这两种说法都不是绝对精确的,但 monad 通常被定义为 "a monoid in the category of endofunctors";一个 Haskell Alternative
is defined as "a monoid on applicative functors", where an applicative functor 是一个 "strong lax monoidal functor"。现在这两个定义听起来与无知者(我)非常相似,但结果却大不相同。 alternative 的中性元素的类型为 f a
,因此为 "empty",而 monad 的中性元素的类型为 a -> m a
,因此意义为 "non-empty"; alternative 的操作类型为 f a -> f a -> f a
,monad 的操作类型为 (a -> f b) -> (b -> f c) -> (a -> f c)
。在我看来,真正重要的细节是 内函子类别 与 内函子类别 相比,尽管也许 "strong lax" 细节在替代很重要;但这就是我感到困惑的地方,因为至少在 Haskell 中,monad 最终成为替代品:而且我发现我还没有对这里的所有细节有一个精确的分类理解。
如何准确表达alternative和monad之间的区别,使得它们都是与内函子相关的幺半群,但一个具有"empty"中性而另一个具有"non-empty"中性元素?
这两个概念都与 "monoidal category" 的概念有关,这是一个类别,您可以在其中定义幺半群的概念(以及某些其他类型的代数结构)。您可以将幺半群类别视为:类别 定义一个参数的函数的抽象概念; 幺半群类别 定义零参数或多参数函数的抽象概念。
单子是内函子类别中的幺半群;换句话说,它是一个幺半群,其中乘积(2 个参数的函数)和恒等式(0 个参数的函数)使用由特定(奇异的)幺半群类别(endofunctors 的幺半群类别)定义的多参数函数的概念和组成)。
应用函子是一个幺半群函子。换句话说,它是一个函子,保留了幺半群范畴的所有结构,而不仅仅是使其成为范畴的部分。很明显,这意味着它具有 mapN 函数,用于具有任意数量参数的函数,而不仅仅是一个参数的函数(就像普通的仿函数)。
所以 monad 存在 within 一个特定的幺半群类别(恰好是一个内函子类别),而 applicative functor 映射 between 两个幺半群类别(恰好是同一类别,因此它是一种内函子)。
一般来说,幺半群定义在幺半群范畴中,幺半群是定义了对象和单位对象的某种(张量)乘积的范畴。
最重要的是,类型的范畴是幺半群的:类型a
和b
的乘积只是一个类型对(a, b)
,单位类型是[=13] =].
然后将幺半群定义为具有两个态射的对象m
:
eta :: () -> m
mu :: (m, m) -> m
注意 eta
只是选择了 m
的一个元素,所以它等同于 mempty
,柯里化 mu
变成了通常 mappend
=61=] Monoid
class.
所以这是一个类型和函数的类别,但还有一个单独的类别是内函子和自然变换。它也是一个幺半群类别。两个函子的张量积定义为它们的复合Compose f g
,单位是恒等函子Id
。该类别中的幺半群是单子。和以前一样,我们选择一个对象 m
,但现在它是一个内函子;和两个态射,现在是自然变换:
eta :: Id ~> m
mu :: Compose m m ~> m
在组件中,这两个自然变换变为:
return :: a -> m a
join :: m (m a) -> m a
应用函子也可以定义为函子类别中的幺半群,但具有更复杂的张量积,称为 Day 卷积。或者,等效地,它可以定义为(松散地)保留幺半群结构的函子。
Alternative
是类型类别中的一类幺半群(不是内函子)。这个家族是由应用函子 f
生成的。对于每个类型 a
,我们都有一个幺半群,其 mempty
是 f a
的一个元素,其 mappend
将 f a
对映射到 f a
的元素.这些多态函数称为 empty
和 <|>
.
特别是,empty
必须是一个多态值,即每种类型一个值 a
。例如,对于列表函子,这是可能的,其中一个空列表在 a
中是多态的,或者对于具有多态值 Nothing
的 Maybe
。请注意,这些都是具有不依赖于类型参数的构造函数的多态数据类型。直觉是,如果您将仿函数视为容器,则此构造函数会创建一个空容器。空容器自动多态。
为了用一些 Haskell 代码补充其他答案,这里是我们如何表示日卷积幺半群结构 @Bartosz Milewski 指的是:
data Day f g a = forall x y. Day (x -> y -> a) (f x) (g y)
单位对象是函子Identity
。
然后我们可以将应用class重新表述为关于这个幺半群结构的幺半群对象:
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
的封装版本,同样 dempty
也是 pure
的封装版本。
也许这两种说法都不是绝对精确的,但 monad 通常被定义为 "a monoid in the category of endofunctors";一个 Haskell Alternative
is defined as "a monoid on applicative functors", where an applicative functor 是一个 "strong lax monoidal functor"。现在这两个定义听起来与无知者(我)非常相似,但结果却大不相同。 alternative 的中性元素的类型为 f a
,因此为 "empty",而 monad 的中性元素的类型为 a -> m a
,因此意义为 "non-empty"; alternative 的操作类型为 f a -> f a -> f a
,monad 的操作类型为 (a -> f b) -> (b -> f c) -> (a -> f c)
。在我看来,真正重要的细节是 内函子类别 与 内函子类别 相比,尽管也许 "strong lax" 细节在替代很重要;但这就是我感到困惑的地方,因为至少在 Haskell 中,monad 最终成为替代品:而且我发现我还没有对这里的所有细节有一个精确的分类理解。
如何准确表达alternative和monad之间的区别,使得它们都是与内函子相关的幺半群,但一个具有"empty"中性而另一个具有"non-empty"中性元素?
这两个概念都与 "monoidal category" 的概念有关,这是一个类别,您可以在其中定义幺半群的概念(以及某些其他类型的代数结构)。您可以将幺半群类别视为:类别 定义一个参数的函数的抽象概念; 幺半群类别 定义零参数或多参数函数的抽象概念。
单子是内函子类别中的幺半群;换句话说,它是一个幺半群,其中乘积(2 个参数的函数)和恒等式(0 个参数的函数)使用由特定(奇异的)幺半群类别(endofunctors 的幺半群类别)定义的多参数函数的概念和组成)。
应用函子是一个幺半群函子。换句话说,它是一个函子,保留了幺半群范畴的所有结构,而不仅仅是使其成为范畴的部分。很明显,这意味着它具有 mapN 函数,用于具有任意数量参数的函数,而不仅仅是一个参数的函数(就像普通的仿函数)。
所以 monad 存在 within 一个特定的幺半群类别(恰好是一个内函子类别),而 applicative functor 映射 between 两个幺半群类别(恰好是同一类别,因此它是一种内函子)。
一般来说,幺半群定义在幺半群范畴中,幺半群是定义了对象和单位对象的某种(张量)乘积的范畴。
最重要的是,类型的范畴是幺半群的:类型a
和b
的乘积只是一个类型对(a, b)
,单位类型是[=13] =].
然后将幺半群定义为具有两个态射的对象m
:
eta :: () -> m mu :: (m, m) -> m
注意 eta
只是选择了 m
的一个元素,所以它等同于 mempty
,柯里化 mu
变成了通常 mappend
=61=] Monoid
class.
所以这是一个类型和函数的类别,但还有一个单独的类别是内函子和自然变换。它也是一个幺半群类别。两个函子的张量积定义为它们的复合Compose f g
,单位是恒等函子Id
。该类别中的幺半群是单子。和以前一样,我们选择一个对象 m
,但现在它是一个内函子;和两个态射,现在是自然变换:
eta :: Id ~> m mu :: Compose m m ~> m
在组件中,这两个自然变换变为:
return :: a -> m a join :: m (m a) -> m a
应用函子也可以定义为函子类别中的幺半群,但具有更复杂的张量积,称为 Day 卷积。或者,等效地,它可以定义为(松散地)保留幺半群结构的函子。
Alternative
是类型类别中的一类幺半群(不是内函子)。这个家族是由应用函子 f
生成的。对于每个类型 a
,我们都有一个幺半群,其 mempty
是 f a
的一个元素,其 mappend
将 f a
对映射到 f a
的元素.这些多态函数称为 empty
和 <|>
.
特别是,empty
必须是一个多态值,即每种类型一个值 a
。例如,对于列表函子,这是可能的,其中一个空列表在 a
中是多态的,或者对于具有多态值 Nothing
的 Maybe
。请注意,这些都是具有不依赖于类型参数的构造函数的多态数据类型。直觉是,如果您将仿函数视为容器,则此构造函数会创建一个空容器。空容器自动多态。
为了用一些 Haskell 代码补充其他答案,这里是我们如何表示日卷积幺半群结构 @Bartosz Milewski 指的是:
data Day f g a = forall x y. Day (x -> y -> a) (f x) (g y)
单位对象是函子Identity
。
然后我们可以将应用class重新表述为关于这个幺半群结构的幺半群对象:
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
的封装版本,同样 dempty
也是 pure
的封装版本。