Rey*_*och 8 haskell binary-operators operators monoids
所以,我现在正在学习Haskell,我想确认或揭穿我对monoid的理解.
我从阅读CIS194课程中发现的是,monoid基本上是用于在自定义集上定义自定义二进制操作的"API".
比我去告诉自己更多,我偶然发现了大量非常令人困惑的教程,试图澄清这个问题,所以我不再那么肯定了.
我有不错的数学背景,但我对所有的比喻感到困惑,我正在寻找对我对monoid的理解的明确是/否答案.
在抽象代数中,数学的一个分支,monoid是一个代数结构,具有单个关联二元运算和一个恒等元素.
我认为你的理解是正确的.从编程的角度来看,Monoid是一个必须实现的两个"方法"的接口.
你的描述中似乎唯一缺少的是"身份",没有它你就是在描述一个半群.
任何具有"零"或"空"的东西以及组合两个值的方法都可以是Monoid.需要注意的一点是,可以通过多种方式将集合/类型设置为Monoid,例如通过addition身份0或multiplication带有身份的数字1.
来自Wolfram:
monoid是在关联二元运算下关闭的集合,并且在S中具有标识元素I,使得对于S中的所有a,Ia = aI = a.
来自Wiki:
在抽象代数中,数学的一个分支,monoid是一个代数结构,具有单个关联二元运算和一个恒等元素.
所以你的直觉或多或少是正确的.
你应该记住,它没有为Haskell中的"自定义集"定义,而是一种类型.区别很小(因为类型理论中的类型与集合论中的集合非常相似),但是您可以定义Monoid实例的类型不必是表示数学集的类型.
换句话说:类型描述该类型的所有值的集合.Monoid是一个"接口",它声明任何声称遵守该接口的类型必须提供一个标识值,一个二进制操作组合该类型的两个值,并且有一些方程式应该满足以便所有通用的Monoid操作按预期工作(例如幺半群值列表的一般求和),不产生不合逻辑/不一致的结果.
另请注意,类型中存在标识元素(类型)是类型作为Monoid类的实例所必需的.
例如,自然数在两个加法下形成一个Monoid(identity = 0):
0 + n = n
n + 0 = n
Run Code Online (Sandbox Code Playgroud)
以及乘法(identity = 1):
1 * n = n
n * 1 = n
Run Code Online (Sandbox Code Playgroud)
还列出了一个monoid ++(identity = []):
[] ++ xs = xs
xs ++ [] = xs
Run Code Online (Sandbox Code Playgroud)
同样,类型的函数a -> a在组合下形成一个monoid(identity = id)
id . f = f
f . id = f
Run Code Online (Sandbox Code Playgroud)
因此,重要的是要记住,Monoid不是关于表示集合的类型,而是关于作为集合查看的类型,可以这么说.
作为一个错误构造的Monoid实例的例子,考虑:
import Data.Monoid
newtype MyInt = MyInt Int deriving Show
instance Monoid MyInt where
mempty = MyInt 0
mappend (MyInt a) (MyInt b) = MyInt (a * b)
Run Code Online (Sandbox Code Playgroud)
如果你现在尝试mconcat一个MyInt值列表,你将总是得到MyInt 0结果,因为身份值0和二进制操作*不能很好地一起使用:
?> mconcat [MyInt 1, MyInt 2]
MyInt 0
Run Code Online (Sandbox Code Playgroud)