-
函子是类别之间的结构保留转换。这是一种将对象从一个类别映射到另一个类别的对象,同时保留对象之间的箭头的某种方式 - 将其视为类别同态。
-
内函子是从一类回到同一范畴的函子。
在 JavaScript 中,Array.map 通常可以链接,因为它总是返回 Array。
someArray
.map(f1)
.map(f2)
.map(f3)
...
所以,在第一次考虑(2(时,我只是想"好吧,由于Array是一种具有方法映射的特殊类型,并且它返回相同的类型,因此JavaScript数组必须是endofunctor。
但是,考虑到(1(,我想"等等,它只是所有函子的结构保存功能,不限于内函子吗?
换句话说,说"如果它是可链的,它就是内函子"是否安全?或者它是无效的,因为可链接的映射和 endo- 是另一个概念?
是的,Array.map 是 javascript 中的内函子,因为它通过使用对象作为 self 来返回对象。请注意,仅在 JS 中,因为它仅使用object
.
在像 C# 这样的其他语言中,当你定义一个数组时,你需要给出包含的类型,它们之间的映射成为函子而不是内函子。
它很容易识别。当且仅当类的函子始终返回与自身相同的类时,该函子是内函子。
因此在类MyClass
中,
a: function(){
return this;
},
b: function(){
return new MyClass();
}
这些是内函子。
然而,说链式函子是内函子是不安全的。
简单地想象两个类,class MyClassA()
和class MyClassB()
,两者都有一个共享相同名称的函子(这是通常的(。
在MyClassA
,
changetype: function(){
return MyClassB;
}
反之亦然。
所以,一旦你可以写出类似的东西
a = new MyClassA();
a.changetype().changetype().changetype()......
并且没有麻烦。
因此,如果您发现函子链可,则无法确定它是否是内函子。因为共享同名函子在所有编程语言中都是非常非常典型的。
它是一个函子(或多或少(,而不是内函子。
首先要认识到的是,数学中的函子与编程中的函子不同,就像数学集合论中的类与编程中的类不同一样。在编程中 - 特别是在Haskell中 - 函子是一个接口的名称。是的,一个接口。因为在 Haskell 中,类型类定义了一个接口,而 Functor 是一个类型类的名称,它要求类型实现一个名为"fmap"的函数以满足 Functor 接口。
更多详情请见:https://motts42.blogspot.com/2017/12/functors-according-to-haskell.html
函子类型类看起来像这样,fmap :: (a -> b) -> f a -> f b
。名称"f"、"a"和"b"都是变量类型。因此,例如,fmap 可能会将Box Int
转换为Box String
,或将List String
转换为List Bool
。容器类型(如 Box 或 List(将始终相同,在 fmap 的签名中由类型变量"f"表示。唯一可以更改的部分是容器包含的类型。
Haskell没有定义一种叫做内函子的东西,所以现在我们必须稍微推测一下。毕竟,请记住,Haskell函子是类型的接口,而不是类别之间的转换。在数学中,内函子是将类别映射到自身的函子。在 Haskell 函子的上下文中,我可以解释的最好方法是函子,其中 fmap 的类型变量 "a" 和 "b" 是相同的类型。也就是说,一个fmap函数将一个Box Int
映射到另一个Box Int
,或将一个List String
映射到另一个List String
。
当然,在JavaScript 的数组的情况下,您可以将一个数字数组映射到另一个数字数组,但您绝不仅限于这样做。您可以自由地将任何内容的数组映射到其他任何内容的数组。