我注意到“monad”这个词似乎以一种不一致的方式使用。我开始相信这是因为很多(如果不是大多数)monad教程是由那些刚刚开始自己构建monad的人写的(例如:核废料太空服卷饼),所以这个术语结束了得到了一些过载/损坏。
特别是,我想知道术语“monad”是否可以应用于Maybe,List或IO等类型的单个值,或者术语“monad”是否真的只应用于类型本身。
这是一个微妙的区别,所以也许类比可能会更清楚。在数学中,我们有,环,字段,组等。这些术语适用于整个值集以及可以对它们执行的操作,而不是单个元素。例如,整数(以及加法,否定和乘法的运算)形成一个环。你可以说“整数是一个戒指”,但你永远不会说“5是一个戒指”。
那么,你能说“Just 5
是一个单子”,还是会说“5是一个戒指”?我不知道类别理论,但我的印象是说“Maybe
是一个单子”而不是“Just 5
是一个单子”真的是有意义的。
答案 0 :(得分:19)
“Monad”(和“Functor”)通常被误用作为描述值。
没有价值是monad,functor,monoid,applicative functor等。
只有类型&类型构造函数(高级类型)可以。
当你听到(并且你会)“列表是幺半群”或“函数是monad”等,或者“这个函数以monad为参数”时,不要相信它。
问一下发言者“考虑到Haskells类对类型(包括高阶类型)而不是值进行分类,任何值都是monoid(或monad或......)怎么样?”
列表不是幺半群(等)。 List a
是。
我的猜测是,这种流行的滥用源于具有价值类而非类型类的主流语言,因此习惯性,无意识的价值阶级思维潜入其中。
为什么我们精确地使用语言是否重要? 因为我们用语言思考并且我们建立&通过语言传达理解。 因此,为了有清晰的想法,有助于拥有清晰的语言(或能够随时)。
“我们语言的邋is让我们更容易有愚蠢的想法。重点是这个过程是可逆的。” - George Orwell,Politics and the English Language
编辑:这些评论适用于Haskell,而不是类别理论的更一般设置。
答案 1 :(得分:11)
List
是monad,List a
是一种类型,[]
是List a
(类型的元素)。
从技术上讲,monad是一个具有额外结构的仿函数;在Haskell中,我们只使用Haskell类型的函子到它自己。
因此特别是一个“函数”,它接受一个类型并返回另一个类型(它有类* -> *
)。
List
,State s
,Maybe
等是monad。 State
不是monad,因为它有* -> * -> *
种。
(除了:混淆问题,Monads只是仿函数,如果我给自己一个部分有序的集合A,那么它形成一个类别,如果一个&lt的话,Hom(a,b)= {1 element} ; = b和Hom(a,b)=否则为空。现在任何增加函数f:A - > A形成一个仿函数,monad是那些满足x< = f(x)和f(f(x)的函数))< = f(x),因此f(f(x))= f(x) - 这里的monad在技术上是“A - > A的元素”。另见closure operators。)
(除了2:因为你似乎知道一些数学,我鼓励你阅读类别理论。你会看到代数结构可以看作是由monad引起的。见this excellent blog entry from the excellent blog by Dan Piponi预告片。)
答案 2 :(得分:4)
确切地说,monad是类别理论的结构。他们没有直接的代码对应物。为简单起见,我们来谈谈一般的仿函数而不是monad。在Haskell的情况下,粗略地说,仿函数是从一类类型到一类类型的映射,它们也将第一类中的函数映射到第二类中的函数。 Functor
实例允许您访问映射函数,但不直接捕获仿函数的概念。
然而,可以说Functor
实例中提到的类型构造函数是实际的函子:
instance Functor Tree
在这种情况下,Tree
是仿函数。但是,因为Tree
是一个类型构造函数,所以它不能代表同时构成仿函数的两个映射函数。映射函数的函数称为fmap
。因此,如果您想要精确,则必须说元组(Tree, fmap)
是仿函数,其中fmap
是来自fmap
Tree
的特定Functor
实例。为方便起见,我们再次说Tree
是仿函数,因为相应的fmap
来自其Functor
实例。
请注意,仿函数始终是* -> *
种类型。因此Maybe Int
不是仿函数 - 仿函数是Maybe
。人们经常谈论“国家monad”,这也是不精确的。 State
是一个由无数个状态monad组成的整个家族,正如你在实例中看到的那样:
instance Monad (State s)
对于每种类型s
,类型构造函数State s
(种类* -> *
)是 a 状态monad,其中之一。
答案 3 :(得分:2)
所以,你能说“Just 5是monad”,还是说“5是一个戒指”会不会错误?
你的直觉是完全正确的。 Int
Ring
(或AbelianGroup
或其他)属于Maybe
Monad
(或Functor
或其他)。值(5
,Just 5
等)并不重要。
在代数中,我们说整数集形成一个环;在Haskell中,我们会(非正式地)说Int
是Ring
类型类的成员,或者(稍微更正式地)Ring
实例存在Int
个实例。您可能会发现this proposal有趣和/或有用。无论如何,与monads相同。
我不知道类别理论,但是......
无论如何,如果你对抽象代数了解一两件事,那你就是金色的。
答案 4 :(得分:1)
我会说“Just 5是一个Monad实例的类型”,就像我会说“5是一个有类型的数字(整数)是一个环”。
我使用术语实例,因为在Haskell中你是如何声明类型类的实现的,而Monad就是其中之一。