Homo表示相等,Haskell中的同态与保留结构有关。
例如,类别 functor 中的fmap
函数保留了该结构。
但是同态到底是什么意思?
答案 0 :(得分:7)
什么是“代数结构”?
法律定义的抽象代数研究代数。例如,monoid体现了联想和身份的观念,而群体则增加了可逆性的观念。 The set of axioms and laws of the algebra is also called its "algebraic structure." Confusingly, an algebra itself is also called an "algebraic structure"
一个组的示例是加法运算的整数集合,其同一性为0,反数为-x。一组的另一个示例是在乘法下的一组非零有理数,其同一性为1,反数为1 / x。
现在,让我们看一下组同态。
Let(G,*,e)表示一个组,其中G是载波集,*是运算符,e是标识元素。设F为从组(G,*,e)到组(G',*',e')的组同态,设f为从G到G'的基本函数。
(请注意,the preservation of inverse follows from the above laws。)
这是为组“保留结构”的含义。
对于环,必须保留环结构,对于其他代数结构,依此类推。
请参见this Math Stack Exchange answer。
现在,Haskell呢?
首先,类别由这些对象之间的对象和同构物组成。这些词素可以关联地构成,并且每个对象都有一个 identity morphism ,即组成下的身份元素。
函子是类别之间的态射。在Haskell的上下文中,函子是从Hask到Hask *的内泛函子(内同形映射到其自身)。类型构造函数映射Hask的对象(Haskell类型),而fmap
映射态射(Haskell函数)。函子必须保留同一性和组成的类别结构,因此函子定律:
fmap (g . f) = (fmap g) . (fmap f)
fmap id = id
*请注意,Hask fails the laws in the presence of seq
, so it isn't actually a category。
答案 1 :(得分:3)
Haskell类型不仅是孤立值的集合;它们可以具有将相同类型的两个元素组合在一起并返回该类型的另一个元素的操作。例如,String
和++
,Natural
和+
和*
,Bool
和&&
和||
。
这些操作可能满足或可能不满足某些属性。例如,关联属性(由前面提到的所有操作都满足)或可交换属性(该列表的追加++
不满足)。有时,财产涉及两个不同的运算,例如与+
和*
有关的分配法。
假设我们有两种不同的类型,还有两种不同的操作,每种类型一个。例如,一侧为String
和++
,另一侧为Natural
和+
。操作不同,但是如果斜视一下,我们会看到它们都满足关联属性。
现在,如果我们能找到一个将String
值转换为Natural
值的函数,该函数将+
转换为两个String
的结果总是等于转换原始++
的{{1}}的结果?这比简单地找到任何类型为String
的函数要困难得多。当移至另一侧时,它必须是保留操作结果的函数。两种类型之间的此功能称为<同形同形。
例如,函数String -> Natural
是同态的。两个字符串的串联长度等于原始长度的总和。像length :: String -> Natural
这样的函数但为空列表分配了非零值的函数将不是有效的同态。
请注意,同态可以“擦除”源类型中存在的区别。例如,length
为length
和"foo"
分配了相同的数字。
另一个示例:考虑一侧的类型"bar"
和操作</>
(仅考虑相对文件夹路径)和类型FilePath
和操作{{3} } 在另一。那么函数>>
是同态的。请注意,存在IO ()
,例如IO ()
的值,这些值不代表“更改文件夹”效果,并且永远不会被putStrLn "foo"
“定为目标”。 setCurrentDirectory
不会发生这种情况,其中每个lenght
都是某个Natural
或另一个lenght
中的String
。