在阅读各种关于函数式编程的文章时,我遇到过几次“Functor”这个术语,但作者通常认为读者已经理解了这个术语。在网络上你可以看到一些过于技术性的描述(参见维基百科的文章),也可以看到一些非常模糊的描述(参见ocaml-tutorial网站上关于函数函数的部分)。

有没有人可以定义这个术语,解释它的用法,或者提供一个如何创建和使用函子的例子?

编辑:虽然我对这个术语背后的理论很感兴趣,但我对这个概念的实现和实际应用更感兴趣,而不是理论。

编辑2:看起来好像有一些交叉术语:我特别指的是函数式编程的函子,而不是c++的函数对象。


当前回答

在OCaml中,它是一个参数化模块。

如果您了解c++,可以将OCaml函子视为模板。c++只有类模板,函数子在模块规模上工作。

函数子的一个例子是Map.Make;module StringMap =映射。使(字符串);;构建一个使用字符串键映射的映射模块。

你不能通过多态性实现StringMap这样的东西;你需要对这些键做一些假设。String模块包含对完全有序字符串类型的操作(比较等),函子将链接到String模块包含的操作。你可以用面向对象编程做一些类似的事情,但是你会有方法间接开销。

其他回答

Functor与函数式编程没有特别的关系。它只是一个指向函数或某种对象的“指针”,可以像调用函数一样调用它。

在OCaml中,它是一个参数化模块。

如果您了解c++,可以将OCaml函子视为模板。c++只有类模板,函数子在模块规模上工作。

函数子的一个例子是Map.Make;module StringMap =映射。使(字符串);;构建一个使用字符串键映射的映射模块。

你不能通过多态性实现StringMap这样的东西;你需要对这些键做一些假设。String模块包含对完全有序字符串类型的操作(比较等),函子将链接到String模块包含的操作。你可以用面向对象编程做一些类似的事情,但是你会有方法间接开销。

这里的其他答案是完整的,但我将尝试另一种解释FP使用函子。我们来做个类比:

函子是类型为A的容器,当它受到从A→b映射的函数的作用时,将产生类型为b的容器。

与c++中使用的抽象函数指针不同,这里函子不是函数;相反,它是一种在受到某个函数影响时表现一致的东西。

在函数式编程中,错误处理是不同的。抛出和捕获异常是命令式代码。不是使用try/catch块,而是围绕可能抛出错误的代码创建一个安全框。这是函数式编程中的基本设计模式。包装器对象用于封装可能错误的值。包装器的主要目的是提供一种使用被包装对象的“不同”方式

 const wrap = (val) => new Wrapper(val);

包装可以保护对值的直接访问,以便对它们进行操作 安全而不可改变。因为我们不能直接得到它,所以提取它的唯一方法就是使用恒等函数。

identity :: (a) -> a

这是恒等函数的另一个用例:从封装的类型中功能地提取数据。

Wrapper类型使用映射来安全地访问和操作值。在本例中,我们将恒等函数映射到容器上,以从容器中提取值。使用这种方法,可以在调用函数之前检查是否为null,或者检查是否为空字符串、负数等等。

 fmap :: (A -> B) -> Wrapper[A] -> Wrapper[B]

Fmap,首先打开容器,然后将给定函数应用于它的值,最后将值关闭到相同类型的新容器中。这种类型的函数称为函子。

Fmap在每次调用时返回容器的新副本。 函子没有副作用 函子必须是可组合的

实际上,functor是指在c++中实现调用操作符的对象。在ocaml中,我认为函子指的是将一个模块作为输入并输出另一个模块的东西。