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

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

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

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


当前回答

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

其他回答

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

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

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

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

简单地说,函子或函数对象是可以像函数一样调用的类对象。

在c++中:

这就是写函数的方法

void foo()
{
    cout << "Hello, world! I'm a function!";
}

这就是写函子的方法

class FunctorClass
{
    public:
    void operator ()
    {
        cout << "Hello, world! I'm a functor!";
    }
};

现在你可以这样做:

foo(); //result: Hello, World! I'm a function!

FunctorClass bar;
bar(); //result: Hello, World! I'm a functor!

这样做的好处是可以将state保存在类中——想象一下,如果您想询问一个函数被调用了多少次。没有办法以简洁、封装的方式做到这一点。对于函数对象,它就像任何其他类一样:你有一些实例变量,你在operator()中增加它,还有一些方法来检查这个变量,一切都很整齐。

这个问题的最佳答案在布伦特·约吉(Brent Yorgey)的《type eclassopedia》中找到。

这一期的单子阅读器包含了一个精确的定义,什么是一个函子以及许多其他概念的定义以及一个图表。(Monoid, Applicative, Monad和其他概念被解释和看到与函子的关系)。

http://haskell.org/sitewiki/images/8/85/TMR-Issue13.pdf

摘自Functor的Typeclassopedia: 一个简单的直觉是,一个Functor代表一个容器 类中的每个元素统一应用函数的能力 容器”

但实际上,所有类型的类目都是强烈推荐的,因为它们出奇地简单。在某种程度上,你可以看到这里的类型类与object中的设计模式是平行的,因为它们为给定的行为或能力提供了词汇表。

干杯

有三种不同的意思,没有太大的联系!

In Ocaml it is a parametrized module. See manual. I think the best way to grok them is by example: (written quickly, might be buggy) module type Order = sig type t val compare: t -> t -> bool end;; module Integers = struct type t = int let compare x y = x > y end;; module ReverseOrder = functor (X: Order) -> struct type t = X.t let compare x y = X.compare y x end;; (* We can order reversely *) module K = ReverseOrder (Integers);; Integers.compare 3 4;; (* this is false *) K.compare 3 4;; (* this is true *) module LexicographicOrder = functor (X: Order) -> functor (Y: Order) -> struct type t = X.t * Y.t let compare (a,b) (c,d) = if X.compare a c then true else if X.compare c a then false else Y.compare b d end;; (* compare lexicographically *) module X = LexicographicOrder (Integers) (Integers);; X.compare (2,3) (4,5);; module LinearSearch = functor (X: Order) -> struct type t = X.t array let find x k = 0 (* some boring code *) end;; module BinarySearch = functor (X: Order) -> struct type t = X.t array let find x k = 0 (* some boring code *) end;; (* linear search over arrays of integers *) module LS = LinearSearch (Integers);; LS.find [|1;2;3] 2;; (* binary search over arrays of pairs of integers, sorted lexicographically *) module BS = BinarySearch (LexicographicOrder (Integers) (Integers));; BS.find [|(2,3);(4,5)|] (2,3);;

您现在可以快速添加许多可能的顺序,形成新顺序的方法,轻松地对它们进行二进制或线性搜索。泛型编程。

In functional programming languages like Haskell, it means some type constructors (parametrized types like lists, sets) that can be "mapped". To be precise, a functor f is equipped with (a -> b) -> (f a -> f b). This has origins in category theory. The Wikipedia article you linked to is this usage. class Functor f where fmap :: (a -> b) -> (f a -> f b) instance Functor [] where -- lists are a functor fmap = map instance Functor Maybe where -- Maybe is option in Haskell fmap f (Just x) = Just (f x) fmap f Nothing = Nothing fmap (+1) [2,3,4] -- this is [3,4,5] fmap (+1) (Just 5) -- this is Just 6 fmap (+1) Nothing -- this is Nothing

因此,这是一种特殊的类型构造函数,与Ocaml中的函子关系不大!

在命令式语言中,它是指向函数的指针。