15

我注意到“monad”这个词的使用方式似乎有些不一致。我开始相信这是因为那里的许多(如果不是大多数)monad 教程是由刚刚开始自己​​弄清楚 monad 的人编写的(例如:核废料太空服卷饼),所以这个学期结束了变得有点超载/损坏。

特别是,我想知道术语“monad”是否可以应用于类型的单个值,例如 Maybe、List 或 IO,或者术语“monad”是否真的应该只应用于类型本身。

这是一个微妙的区别,所以也许一个类比可能会更清楚。在数学中,我们有环、场、群等。这些术语适用于整个值集以及可以对它们执行的操作,而不是单个元素。例如,整数(连同加法、否定和乘法运算)形成一个环。你可以说“整数是一个环”,但你永远不会说“5 是一个环”。

那么,你能说“Just 5是一个单子”,还是说“5是一个环”是错误的?我不知道范畴论,但我的印象是说“Maybe是一个单子”而不是“Just 5是一个单子”才有意义。

4

5 回答 5

19

“Monad”(和“Functor”)通常被用作描述值。没有值是 monad、functor、monoid、applicative functor 等。只有类型和类型构造函数(更高种类的类型)可以。当你听到(你会听到)“列表是幺半群”或“函数是单子”等,或者“这个函数需要一个单子作为参数”时,不要相信它。问演讲者“考虑到 Haskells 类对类型(包括高阶类)而不是值进行分类,任何值怎么可能是幺半群(或单子或……) ?” 列表不是幺半群(等)。List a是。

我的猜测是,这种流行的误用源于具有价值类而不是类型类的主流语言,因此习惯性的、无意识的价值类思维潜入其中。

为什么我们是否准确地使用语言很重要?因为我们用语言思考,我们通过语言建立和传达理解。所以为了有清晰的想法,有清晰的语言是有帮助的(或者能够随时)。

“我们语言的邋遢让我们更容易产生愚蠢的想法。关键是这个过程是可逆的。” - 乔治奥威尔,政治与英语

编辑:这些评论适用于 Haskell,而不适用于更一般的范畴论设置。

于 2012-06-21T16:52:25.800 回答
11

List是一个单子,List a是一个类型,并且[]是一个List a(类型的元素)。

从技术上讲,monad 是一个具有额外结构的函子。在 Haskell 中,我们只使用 Haskell 类型类别中的函子。

因此,它特别是一个“函数”,它接受一种类型并返回另一种类型(它有 kind * -> *)。

List, State s, Maybe, 等是单子。State不是单子,因为它有 kind * -> * -> *

(顺便说一句:为了混淆问题,Monads 只是函子,如果我给自己一个偏序集合 A,那么它形成一个类别, Hom(a, b) = { 1 element } if a <= b and Hom(a , b) = 否则为空 现在任何递增函数 f : A -> A 形成一个函子,单子是那些满足 x <= f(x) 和 f(f(x)) <= f(x) 的函数,因此 f(f(x)) = f(x) - 这里的 monad 在技术上是“A -> A 的元素”。另见闭包运算符。)

(旁白 2:由于您似乎了解一些数学知识,因此我鼓励您阅读范畴论。您会发现代数结构可以看作是由单子产生的。请参阅Dan Piponi 的优秀博客中的这篇优秀博客条目预告片。)

于 2012-06-18T19:55:59.997 回答
4

确切地说,单子是范畴论的结构。他们没有直接对应的代码。为简单起见,让我们讨论通用函子而不是 monad。在 Haskell 的情况下,大致来说,函子是从一类类型到一类类型的映射,它也将第一类中的函数映射到第二类中的函数。该Functor实例使您可以访问映射函数,但不直接捕获函子的概念。

然而,公平地说,实例中提到的类型构造函数Functor是实际的函子:

instance Functor Tree

在这种情况下Tree是函子。但是,因为Tree是类型构造函数,它不能代表同时生成函子的两个映射函数。映射函数的函数称为fmap。因此,如果您想精确,则必须说元组(Tree, fmap)是函子,fmap特定fmapfromTreeFunctor实例在哪里。再次为方便起见,我们称其Tree为函子,因为对应的fmap来自其Functor实例。

请注意,函子始终是 kind 的类型* -> *。所以Maybe Int不是函子——函子是Maybe。人们也经常谈论“国家单子”,这也是不准确的。 State是一个包含无限多个状态单子的整个家族,如您在实例中所见:

instance Monad (State s)

对于每种类型s,类型构造函数State s(种类* -> *)都是一个状态单子,是众多单子之一。

于 2012-06-18T20:35:17.967 回答
2

那么,你能说“Just 5 is a monad”,还是说“5 is a ring”是错误的?

你的直觉是完全正确的。Intis to Ring( AbelianGrouporwhat) as Maybeis to Monad( Functororwhat)。值(5Just 5等)并不重要。

在代数中,我们说整数的集合形成一个环;在 Haskell 中,我们会(非正式地)说它Int是类型类的成员,或者(稍微Ring更正式地)存在. 你可能会觉得这个提议很有趣和/或有用。无论如何,同样的处理单子。RingInt

我不知道范畴论,但是...

无论如何,如果您对抽象代数有所了解,那么您就是金子。

于 2012-06-21T21:13:20.550 回答
1

我会说“只有 5 是 Monad 的实例类型”,就像我会说“5 是一个具有类型(整数)是一个环的数字”。

我使用术语实例是因为在 Haskell 中您如何声明类型类的实现,而 Monad 就是其中之一。

于 2012-06-16T22:01:38.600 回答