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

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

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

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


当前回答

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

其他回答

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

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

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

“函子”这个词来自范畴论,范畴论是数学中一个非常普遍、非常抽象的分支。函数式语言的设计者至少以两种不同的方式借用了它。

In the ML family of languages, a functor is a module that takes one or more other modules as a parameter. It's considered an advanced feature, and most beginning programmers have difficulty with it. As an example of implementation and practical use, you could define your favorite form of balanced binary search tree once and for all as a functor, and it would take as a parameter a module that provides: The type of key to be used in the binary tree A total-ordering function on keys Once you've done this, you can use the same balanced binary tree implementation forever. (The type of value stored in the tree is usually left polymorphic—the tree doesn't need to look at values other than to copy them around, whereas the tree definitely needs to be able to compare keys, and it gets the comparison function from the functor's parameter.) Another application of ML functors is layered network protocols. The link is to a really terrific paper by the CMU Fox group; it shows how to use functors to build more complex protocol layers (like TCP) on type of simpler layers (like IP or even directly over Ethernet). Each layer is implemented as a functor that takes as a parameter the layer below it. The structure of the software actually reflects the way people think about the problem, as opposed to the layers existing only in the mind of the programmer. In 1994 when this work was published, it was a big deal. For a wild example of ML functors in action, you could see the paper ML Module Mania, which contains a publishable (i.e., scary) example of functors at work. For a brilliant, clear, pellucid explanation of the ML modules system (with comparisons to other kinds of modules), read the first few pages of Xavier Leroy's brilliant 1994 POPL paper Manifest Types, Modules, and Separate Compilation. In Haskell, and in some related pure functional language, Functor is a type class. A type belongs to a type class (or more technically, the type "is an instance of" the type class) when the type provides certain operations with certain expected behavior. A type T can belong to class Functor if it has certain collection-like behavior: The type T is parameterized over another type, which you should think of as the element type of the collection. The type of the full collection is then something like T Int, T String, T Bool, if you are containing integers, strings, or Booleans respectively. If the element type is unknown, it is written as a type parameter a, as in T a. Examples include lists (zero or more elements of type a), the Maybe type (zero or one elements of type a), sets of elements of type a, arrays of elements of type a, all kinds of search trees containing values of type a, and lots of others you can think of. The other property that T has to satisfy is that if you have a function of type a -> b (a function on elements), then you have to be able to take that function and product a related function on collections. You do this with the operator fmap, which is shared by every type in the Functor type class. The operator is actually overloaded, so if you have a function even with type Int -> Bool, then fmap even is an overloaded function that can do many wonderful things: Convert a list of integers to a list of Booleans Convert a tree of integers to a tree of Booleans Convert Nothing to Nothing and Just 7 to Just False In Haskell, this property is expressed by giving the type of fmap: fmap :: (Functor t) => (a -> b) -> t a -> t b where we now have a small t, which means "any type in the Functor class." To make a long story short, in Haskell a functor is a kind of collection for which if you are given a function on elements, fmap will give you back a function on collections. As you can imagine, this is an idea that can be widely reused, which is why it is blessed as part of Haskell's standard library.

像往常一样,人们继续发明新的、有用的抽象,您可能想要研究应用函子,对此最好的参考可能是Conor McBride和Ross Paterson撰写的一篇名为《带效果的应用编程》的论文。

在投票最多的答案下,网友Wei Hu问道:

我理解ml -函子和haskell -函子,但缺乏 将它们联系在一起的洞察力。这两者之间是什么关系 二,在分类理论的意义上?

注:本人不懂ML,如有错误请见谅。

让我们首先假设我们都熟悉“范畴”和“函子”的定义。

一个紧凑的答案是,“haskell -函子”是(endo-)函子F: Hask -> Hask,而“ML-函子”是函子G: ML- > ML'。

这里,Hask是由Haskell类型和它们之间的函数组成的类别,类似地,ML和ML'是由ML结构定义的类别。

注意:将Hask作为一个类别存在一些技术问题,但有一些方法可以绕过它们。

从范畴论的角度来看,这意味着hask -函子是Haskell类型的映射F:

data F a = ...

伴随着Haskell函数的map fmap:

instance Functor F where
    fmap f = ...

ML是差不多的,尽管我不知道有一个规范的fmap抽象,所以让我们定义一个:

signature FUNCTOR = sig
  type 'a f
  val fmap: 'a -> 'b -> 'a f -> 'b f
end

f映射ml -类型fmap映射ml -函数

functor StructB (StructA : SigA) :> FUNCTOR =
struct
  fmap g = ...
  ...
end

是一个函子F: StructA -> StructB。

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

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中的函子关系不大!

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

考虑到其他的答案和我现在要发布的内容,我想说这是一个相当沉重的重载词,但无论如何……

关于Haskell中'functor'这个词的含义,可以问GHCi:

Prelude> :info Functor
class Functor f where
  fmap :: forall a b. (a -> b) -> f a -> f b
  (GHC.Base.<$) :: forall a b. a -> f b -> f a
        -- Defined in GHC.Base
instance Functor Maybe -- Defined in Data.Maybe
instance Functor [] -- Defined in GHC.Base
instance Functor IO -- Defined in GHC.Base

基本上,Haskell中的函子是可以被映射的。另一种说法是,函子是可以被视为容器的东西,它可以被要求使用给定的函数来转换它所包含的值;因此,对于列表,fmap与map重合,对于Maybe, fmap f (Just x) = Just (f x), fmap f Nothing = Nothing等。

函子类型类小节和《Learn You a Haskell for Great Good》的函子、应用函子和Monoids小节给出了一些例子,说明这个特定概念在哪里有用。(总结一下:很多地方!: -))

请注意,任何单子都可以被视为函子,事实上,正如Craig Stuntz所指出的,最常用的函子往往是单子……对了,有时使一个类型成为Functor类型类的实例是很方便的,而不需要麻烦地使它成为一个单子。(例如,在Control中的ZipList的情况下。适用,在前面提到的页面之一。)