这些陈述或许都不是绝对精确的,但是monad通常被定义为“endofunctors类别中的monoid”; Haskell Alternative
被定义为“应用仿函数上的一个幺半群”,其中applicative functor是一个“强疏松的幺正函子”。现在这两个定义听起来非常类似于无知(我),但工作方式有很大不同。替代的中性元素具有类型f a
,因此是“空”,并且对于monad具有类型a -> m a
,因此具有“非空”的意义;替代的操作具有类型f a -> f a -> f a
,并且monad的操作具有类型(a -> f b) -> (b -> f c) -> (a -> f c)
。在我看来,真正重要的细节是在endofunctors 类别 over endofunctors ,尽管替代方案中的“强松弛”细节可能很重要;但这就是我感到困惑的地方,因为至少在Haskell中,monads最终成为替代品:我发现我还没有对这里的所有细节进行精确的分类理解。
如何精确地表达替代和monad之间的区别,使得它们都是与endofunctors相关的幺半群,然而一个具有“空”中性而另一个具有“非空”中性元素?
答案 0 :(得分:19)
通常,幺半群是在幺半群类别中定义的,幺半群类别是定义对象和单位对象的某种(张量)乘积的类别。
最重要的是,类型的类别是单一的:类型a
和b
的乘积只是一种对(a, b)
,单位类型是()
然后将一个幺半群定义为具有两个态射的对象m
:
eta :: () -> m mu :: (m, m) -> m
请注意,eta
只选择m
的元素,因此它等同于mempty
,并且curry mu
变为mappend
通常的Haskell Monoid
类。
这是一类类型和功能,但也有一个单独的endofunctors和自然转换类别。它也是一个幺半群类别。两个仿函数的张量积被定义为它们的组合Compose f g
,而unit是身份仿函数Id
。该类别中的幺半群是monad。和以前一样,我们选择一个对象m
,但现在它是一个endofunctor;和两个态射,现在是自然变换:
eta :: Id ~> m mu :: Compose m m ~> m
在组件中,这两个自然变换成为:
return :: a -> m a join :: m (m a) -> m
应用仿函数也可以被定义为仿函数类别中的幺半群,但是具有称为日卷积的更复杂的张量积。或者,等效地,它可以被定义为(松散地)保留幺半群结构的仿函数。
Alternative
是类型(不是endofunctors)类别中的幺半群。此系列由应用仿函数f
生成。对于每种类型a
,我们都有一个幺半群,其mempty
是f a
的元素,其mappend
将f a
对映射到f a
的元素。这些多态函数称为empty
和<|>
。
特别是,empty
必须是多态值,这意味着每种类型a
都有一个值。例如,这可能是列表仿函数,其中空列表在a
中是多态的,或者对于具有多态值Maybe
的{{1}}。请注意,这些都是具有不依赖于类型参数的构造函数的多态数据类型。直觉是,如果您将仿函数视为容器,则此构造函数会创建并清空容器。空容器是自动多态的。
答案 1 :(得分:4)
这两个概念都与“幺半群”类别&#34;的概念联系在一起,这是一个类别,你可以定义一个幺半群的概念(和某些其他类型的代数结构)。您可以将monoidal类别视为: category 定义一个参数的函数的抽象概念; monoidal类定义零参数或多个参数的函数的抽象概念。
monad是endofunctors类别中的monoid;换句话说,它是一个幺半群,其中产品(2个参数的函数)和身份(0个参数的函数)使用由特定(奇异)幺半群类别(幺半群)定义的多参数函数的概念终结者和组成的类别)。
应用仿函数是一个幺正仿函数。换句话说,它是一个保留了幺半群类别的所有结构的仿函数,而不仅仅是使它成为一个类别的部分。很明显,这意味着它具有mapN函数,用于具有任意数量参数的函数,而不仅仅是一个参数的函数(就像普通仿函数一样)。
所以monad在中存在特定的monoidal类别(恰好是endofunctors的类别),而applicative functor在两个monoidal类别之间映射(恰好属于同一类别,因此它是一种终结者。)
答案 2 :(得分:1)
用一些Haskell代码补充其他答案,这是我们如何表示Day卷积单项式结构@Bartosz Milewski所指:
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
的包装版本,同样也是dempty
的{{1}}的包装版本。