在函数式编程中,什么是函子?

时间:2020-12-24 20:03:56

I've come across the term 'Functor' a few times while reading various articles on functional programming, but the authors typically assume the reader already understands the term. Looking around on the web has provided either excessively technical descriptions (see the Wikipedia article) or incredibly vague descriptions (see the section on Functors at this ocaml-tutorial website).

在阅读有关函数编程的各种文章时,我遇到过“函数者”一词,但作者通常假定读者已经理解了这个词。浏览网页时,要么提供了过于技术性的描述(请参阅*的文章),要么提供了极其模糊的描述(请参阅这个ocml -tutorial网站上关于函数者的部分)。

Can someone kindly define the term, explain its use, and perhaps provide an example of how Functors are created and used?

有人能好心地定义这个术语,解释它的用法吗?也许还能提供一个如何创建和使用函数的例子?

Edit: While I am interested in the theory behind the term, I am less interested in the theory than I am in the implementation and practical use of the concept.

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

Edit 2: Looks like there is some cross-terminoligy going on: I'm specifically referring to the Functors of functional programming, not the function objects of C++.

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

17 个解决方案

#1


251  

The word "functor" comes from category theory, which is a very general, very abstract branch of mathematics. It has been borrowed by designers of functional languages in at least two different ways.

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

  • 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.

    在ML语言家族中,函数器是一个以一个或多个其他模块作为参数的模块。它被认为是一种高级特性,大多数初级程序员都很难使用它。

    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

      键上的total-order函数。

    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.

    ML函数的另一个应用是分层网络协议。链接到CMU Fox集团的一篇很棒的论文;它展示了如何使用函子在更简单的层(如IP层,甚至直接通过以太网)上构建更复杂的协议层(如TCP层)。每一层都被实现为一个函子,以其下面的层作为参数。软件的结构实际上反映了人们思考问题的方式,而不是只存在于程序员头脑中的层。1994年,当这本书出版的时候,是一件大事。

    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.

    对于一个ML函数的野生示例,您可以看到包含可发布的(例如,在工作中函数的例子。对于ML模块系统(与其他类型的模块进行比较)的精彩、清晰、清晰的解释,请阅读Xavier Leroy 1994年的brilliant POPL论文清单类型、模块和单独编译的前几页。

  • 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:

    在Haskell中,在一些相关的纯函数语言中,Functor是一个类型类。类型属于类型类(或者更严格地说,类型是“类型类”的实例),当类型提供具有特定预期行为的某些操作时。如果类型T具有某种类似集合的行为,则它可以属于类函子:

    • 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.

      类型T在另一个类型上被参数化,您应该将其视为集合的元素类型。如果分别包含整数、字符串或布尔值,则完整集合的类型是T Int、T String、T Bool。如果元素类型未知,则将其作为类型参数a写入,如在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.

      示例包括列表(类型a的零或多个元素)、可能类型(类型a的零或一个元素)、类型a的元素集、类型a的元素数组、包含类型a的值的所有搜索树,以及许多您可以想到的其他元素。

    • 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

      T要满足的另一个性质是如果你有一个a - >b类型的函数(一个元素上的函数)那么你必须能够把这个函数和与集合相关的函数乘积。您可以使用操作符fmap来实现这一点,它由Functor类型类中的每个类型共享。运算符实际上是重载的,所以如果你有一个函数,即使类型是Int -> Bool,那么

      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

        将0转换为0,将7转换为False

      In Haskell, this property is expressed by giving the type of fmap:

      在Haskell中,这个属性通过提供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."

      我们现在有一个小t,意思是“函数类中的任何类型”

    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.

    长话短说,在Haskell中,函数是一种集合,如果给你一个关于元素的函数,fmap会给你一个关于集合的函数。正如您可以想象的,这是一个可以被广泛重用的想法,这就是为什么它是Haskell标准库的一部分。

As usual, people continue to invent new, useful abstractions, and you may want to look into applicative functors, for which the best reference may be a paper called Applicative Programming with Effects by Conor McBride and Ross Paterson.

和往常一样,人们不断地发明新的、有用的抽象,您可能想要研究应用函数,其中最好的参考可能是Conor McBride和Ross Paterson所著的《应用程序编程》(applicative Programming)论文。

#2


49  

Other answers here are complete, but I'll try another explanation of the FP use of functor. Take this as analogy:

这里的其他答案是完整的,但是我将尝试另一种关于泛函子使用的解释。把这个类比:

A functor is a container of type a that, when subjected to a function that maps from ab, yields a container of type b.

函子是一种容器类型的,当受到一个函数映射从→b,收益率b型的容器。

Unlike the abstracted-function-pointer use in C++, here the functor is not the function; rather, it's something that behaves consistently when subjected to a function.

与c++中的抽象函数指针不同,这里的函数不是函数;相反,当受到一个函数时,它的行为是一致的。

#3


36  

There are three different meanings, not much related!

有三种不同的含义,没有多少关联!

  • 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)

    在Ocaml中,它是一个参数化的模块。参见手册。我认为探索它们的最好方法是举例:(写得快,可能有错误)

    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);;
    

You can now add quickly many possible orders, ways to form new orders, do a binary or linear search easily over them. Generic programming FTW.

现在,您可以快速添加许多可能的订单,生成新订单的方法,轻松地进行二进制或线性搜索。泛型编程增值。

  • 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.

    在像Haskell这样的函数式编程语言中,它意味着可以“映射”的某些类型构造函数(如列表、集合等参数化类型)。准确地说,一个f函子有(a -> b) -> (f a -> f b),这源于范畴理论。你链接到的*文章就是这个用法。

    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
    

So, this is a special kind of a type constructors, and has little to do with functors in Ocaml!

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

  • In imperative languages, it is a pointer to function.
  • 在命令式语言中,它是指向函数的指针。

#4


15  

In OCaml, it's a parameterised module.

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

If you know C++, think of an OCaml functor as a template. C++ only has class templates, and functors work at the module scale.

如果您知道c++,可以将OCaml函数当作模板。c++只具有类模板,函数符在模块范围内工作。

An example of functor is Map.Make; module StringMap = Map.Make (String);; builds a map module that works with String-keyed maps.

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

You couldn't achieve something like StringMap with just polymorphism; you need to make some assumptions on the keys. The String module contains the operations (comparison, etc) on a totally ordered string type, and the functor will link against the operations the String module contains. You could do something similar with object-oriented programming, but you'd have method indirection overhead.

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

#5


12  

You got quite a few good answers. I'll pitch in:

你得到了不少好答案。我将投入:

A functor, in the mathematical sense, is a special kind of function on an algebra. It is a minimal function which maps an algebra to another algebra. "Minimality" is expressed by the functor laws.

在数学意义上,函数是代数上的一种特殊的函数。它是一个将代数映射到另一个代数的极小函数。“极小”是由函子定律表示的。

There are two ways to look at this. For example, lists are functors over some type. That is, given an algebra over a type 'a', you can generate a compatible algebra of lists containing things of type 'a'. (For example: the map that takes an element to a singleton list containing it: f(a) = [a]) Again, the notion of compatibility is expressed by the functor laws.

有两种方式来看待这个问题。例如,列表是某种类型的函数。也就是说,给定一个关于a类型的代数,您可以生成包含a类型的东西的列表的兼容代数。(例如:将一个元素带到包含它的单例列表的映射:f(a) = [a]))同样,兼容性的概念由函数法则表示。

On the other hand, given a functor f "over" a type a, (that is, f a is the result of applying the functor f to the algebra of type a), and function from g: a -> b, we can compute a new functor F = (fmap g) which maps f a to f b. In short, fmap is the part of F that maps "functor parts" to "functor parts", and g is the part of the function that maps "algebra parts" to "algebra parts". It takes a function, a functor, and once complete, it IS a functor too.

另一方面,鉴于函子f / a型,(也就是说,f是应用函子的结果f的代数a型),并从g函数:a - > b,我们可以计算一个新的函子f =(fmap g)映射f a到f b。简而言之,fmap是f的一部分映射“函子零件”“函子零件”,和g函数的一部分,“代数”映射到“代数部分”。它需要一个函数,一个函数,一旦完成,它也是一个函数。

It might seem that different languages are using different notions of functors, but they're not. They're merely using functors over different algebras. OCamls has an algebra of modules, and functors over that algebra let you attach new declarations to a module in a "compatible" way.

似乎不同的语言使用不同的功能函数,但它们不是。它们只是在不同的代数上使用函子。OCamls有一个模块代数,而该代数上的函数可以让您以“兼容”的方式将新的声明附加到模块上。

A Haskell functor is NOT a type class. It is a data type with a free variable which satisfies the type class. If you're willing to dig into the guts of a datatype (with no free variables), you can reinterpret a data type as a functor over an underlying algebra. For example:

Haskell函数不是类型类。它是一个带有*变量的数据类型,满足类型类。如果您愿意深入研究数据类型的本质(没有*变量),您可以在底层代数中将数据类型重新解释为函数。例如:

data F = F Int

数据F = F Int。

is isomorphic to the class of Ints. So F, as a value constructor, is a function that maps Int to F Int, an equivalent algebra. It is a functor. On the other hand, you don't get fmap for free here. That's what pattern matching is for.

是Ints类的同构。所以F,作为一个值构造函数,是一个将Int映射到F Int的函数,等价的代数。这是一个函子。另一方面,你不能在这里免费获得fmap。这就是模式匹配的作用。

Functors are good for "attaching" things to elements of algebras, in an algebraically compatible way.

函数函数可以很好地以代数相容的方式将东西“附加”到代数的元素中。

#6


7  

There is a pretty good example in the O'Reilly OCaml book that's on Inria's website (which as of writing this is unfortunately down). I found a very similar example in this book used by caltech: Introduction to OCaml (pdf link). The relevant section is the chapter on functors (Page 139 in the book, page 149 in the PDF).

在Inria网站上的O'Reilly OCaml书中有一个很好的例子(不幸的是,在写这本书的时候,它已经被删除了)。我在加州理工学院使用的这本书中发现了一个非常相似的例子:OCaml简介(pdf链接)。相关章节是关于函数者的一章(书139页,PDF页149页)。

In the book they have a functor called MakeSet which creates a data structure that consists of a list, and functions to add an element, determine if an element is in the list, and to find the element. The comparison function that is used to determine if it's in/not in the set has been parametrized (which is what makes MakeSet a functor instead of a module).

在书中,他们有一个名为MakeSet的函数,它创建一个由列表组成的数据结构,以及添加元素的函数,确定元素是否在列表中,并查找元素。用来确定它是否在集合中的比较函数已经被参数化了(这是使MakeSet成为一个函数而不是模块的原因)。

They also have a module that implements the comparison function so that it does a case insensitive string compare.

它们还有一个实现比较函数的模块,以便它执行不区分大小写的字符串比较。

Using the functor and the module that implements the comparison they can create a new module in one line:

使用功能函数和实现比较的模块,可以在一行中创建一个新模块:

module SSet = MakeSet(StringCaseEqual);;

that creates a module for a set data structure that uses case insensitive comparisons. If you wanted to create a set that used case sensitive comparisons then you would just need to implement a new comparison module instead of a new data structure module.

这就为一个用例不敏感比较的set数据结构创建了一个模块。如果您想要创建一个使用区分大小写比较的集合,那么您只需实现一个新的比较模块,而不是一个新的数据结构模块。

Tobu compared functors to templates in C++ which I think is quite apt.

Tobu将函数与c++中的模板进行了比较,我认为这是很合适的。

#7


7  

The best answer to that question is found in "Typeclassopedia" by Brent Yorgey.

这个问题的最佳答案是布兰特·约克吉的《类型学》。

This issue of Monad Reader contain a precise definition of what a functor is as well as many definition of other concepts as well as a diagram. (Monoid, Applicative, Monad and other concept are explained and seen in relation to a functor).

Monad阅读器的这个问题包含了一个函数的精确定义,以及其他概念的定义以及一个图表。(单线、应用、单点和其他概念在与函子的关系中被解释和看到)。

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

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

excerpt from Typeclassopedia for Functor: "A simple intuition is that a Functor represents a “container” of some sort, along with the ability to apply a function uniformly to every element in the container"

摘自Typeclassopedia对于Functor:“一个简单的直觉是:一个函数表示某种“容器”,以及将函数均匀地应用到容器中的每个元素的能力”

But really the whole typeclassopedia is a highly recommended reading that is surprisingly easy. In a way you can see the typeclass presented there as a parallel to design pattern in object in the sense that they give you a vocabulary for given behavior or capability.

但实际上,整部类型学都是高度推荐的阅读材料,非常简单。在某种程度上,您可以看到,在对象中,类型化类与设计模式是并行的,因为它们为给定的行为或能力提供了词汇表。

Cheers

干杯

#8


5  

Here's an article on functors from a programming POV, followed up by more specifically how they surface in programming languages.

这里有一篇关于编程POV中的函子的文章,接着是关于它们在编程语言中的表现形式。

The practical use of a functor is in a monad, and you can find many tutorials on monads if you look for that.

函数的实际使用是在monad中,如果您查找monads,您可以找到很多关于monads的教程。

#9


5  

Given the other answers and what I'm going to post now, I'd say that it's a rather heavily overloaded word, but anyway...

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

For a hint regarding the meaning of the word 'functor' in Haskell, ask GHCi:

要了解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

So, basically, a functor in Haskell is something that can be mapped over. Another way to say it is that a functor is something which can be regarded as a container which can be asked to use a given function to transform the value it contains; thus, for lists, fmap coincides with map, for Maybe, fmap f (Just x) = Just (f x), fmap f Nothing = Nothing etc.

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

The Functor typeclass subsection and the section on Functors, Applicative Functors and Monoids of Learn You a Haskell for Great Good give some examples of where this particular concept is useful. (A summary: lots of places! :-))

函数类型学子节和函数、应用函数和学习Haskell的单类的一节很好地给出了这个特殊概念的一些例子。(总结:很多地方!:-))

Note that any monad can be treated as a functor, and in fact, as Craig Stuntz points out, the most often used functors tend to be monads... OTOH, it is convenient at times to make a type an instance of the Functor typeclass without going to the trouble of making it a Monad. (E.g. in the case of ZipList from Control.Applicative, mentioned on one of the aforementioned pages.)

请注意,任何monad都可以被视为一个函子,事实上,正如Craig Stuntz所指出的,最常用的函子往往是monads…OTOH,有时可以方便地将一个类型创建为一个函数类型类型的实例,而不必麻烦地将其创建为Monad。(例如,在从控制链表的情况下。适用的,上面提到过)

#10


5  

In a comment to the top-voted answer, user Wei Hu asks:

在对投票结果的评论中,用户胡伟问道:

I understand both ML-functors and Haskell-functors, but lack the insight to relate them together. What's the relationship between these two, in a category-theoretical sense?

我理解ML-functors和haskelly -functors,但我没有把它们联系在一起的洞察力。在分类理论意义上,这两者之间的关系是什么?

Note: I don't know ML, so please forgive and correct any related mistakes.

注意:我不知道ML,所以请原谅并改正相关错误。

Let's initially assume that we are all familiar with the definitions of 'category' and 'functor'.

让我们先假设我们都熟悉“category”和“functor”的定义。

A compact answer would be that "Haskell-functors" are (endo-)functors F : Hask -> Hask while "ML-functors" are functors G : ML -> ML'.

一个简洁的答案是“haskelly -functors”(endo-)是F: Hask -> Hask,而“ML- >”是G: ML- > ML的functors。

Here, Hask is the category formed by Haskell types and functions between them, and similarly ML and ML' are categories defined by ML structures.

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

Note: There are some technical issues with making Hask a category, but there are ways around them.

注意:创建Hask有一些技术问题,但是有一些方法可以解决这些问题。

From a category theoretic perspective, this means that a Hask-functor is a map F of Haskell types:

从范畴理论的角度来看,这意味着Hask-functor是Haskell类型的map F:

data F a = ...

along with a map fmap of Haskell functions:

连同Haskell函数的地图fmap:

instance Functor F where
    fmap f = ...

ML is pretty much the same, though there is no canonical fmap abstraction I am aware of, so let's define one:

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

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

That is f maps ML-types and fmap maps ML-functions, so

即f映射ml类型,fmap映射ml函数

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

is a functor F: StructA -> StructB.

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

#11


3  

"Functor is mapping of objects and morphisms that preserves composition and identity of a category."

“函子是对象和形态的映射,保存了一个类别的组成和特征。”

Lets define what is a category ?

让我们定义什么是类别?

It's a bunch of objects!

它是一堆东西!

Draw a few dots (for now 2 dots, one is 'a' another is 'b') inside a circle and name that circle A(Category) for now.

画几个点(现在有两个点,一个是“a”,另一个是“b”)在一个圆里,现在把这个圆命名为a(类别)。

What does the category holds ?

这个类别包含什么?

Composition between objects and Identity function for every object.

对象之间的组合和每个对象的恒等函数。

So, we have to map the objects and preserve the composition after applying our Functor.

因此,我们需要映射对象并在应用函数之后保存合成。

Lets imagine 'A' is our category which has objects ['a', 'b'] and there exists a morphism a -> b

假设“A”是我们的类别,它有对象[A', 'b'],并且存在一个morphism A -> b

Now, we have to define a functor which can map these objects and morphisms into another category 'B'.

现在,我们需要定义一个函数,它可以将这些对象和morphisms映射到另一个类别'B'。

Lets say the functor is called 'Maybe'

假设这个函数叫做" Maybe "

data Maybe a = Nothing | Just a

So, The category 'B' looks like this.

B类是这样的。

Please draw another circle but this time with 'Maybe a' and 'Maybe b' instead of 'a' and 'b'.

请再画一个圆,这次用“也许a”和“也许b”代替“a”和“b”。

Everything seems good and all the objects are mapped

一切看起来都很好,所有的对象都被映射了。

'a' became 'Maybe a' and 'b' became 'Maybe b'.

“a”变成了“也许a”,“b”变成了“也许b”。

But the problem is we have to map the morphism from 'a' to 'b' as well.

但是问题是我们也必须把这个符号从a映射到b。

That means morphism a -> b in 'A' should map to morphism 'Maybe a' -> 'Maybe b'

这意味着a -> b在" a "中应该映射到"可能a " -可能b "

morphism from a -> b is called f, then morphism from 'Maybe a' -> 'Maybe b' is called 'fmap f'

a - >b的morphism被称为f,而'Maybe a' -> 'Maybe b'的morphism被称为'fmap f'

Now lets see what function 'f' was doing in 'A' and see if we can replicate it in 'B'

现在我们来看看函数f在A中的作用看看能否在B中复制它

function definition of 'f' in 'A':

f在A中的函数定义:

f :: a -> b

f takes a and returns b

f取a,返回b

function definition of 'f' in 'B' :

f在B中的函数定义:

f :: Maybe a -> Maybe b

f takes Maybe a and return Maybe b

f取a,返回b

lets see how to use fmap to map the function 'f' from 'A' to function 'fmap f' in 'B'

让我们看看如何使用fmap将函数f从A映射到B的fmap f

definition of fmap

fmap的定义

fmap :: (a -> b) -> (Maybe a -> Maybe b)
fmap f Nothing = Nothing
fmap f (Just x) = Just(f x)

So, what are we doing here ?

那么,我们在这里做什么呢?

We are applying the function 'f' to 'x' which is of type 'a'. Special pattern matching of 'Nothing' comes from the definition of Functor Maybe.

我们将函数f应用到x,类型为a。“无”的特殊模式匹配可能来自于函子的定义。

So, we mapped our objects [a, b] and morphisms [ f ] from category 'A' to category 'B'.

因此,我们将我们的对象(a, b)和morphisms [f]从类别a映射到类别b。

Thats Functor!

这函子!

在函数式编程中,什么是函子?

#12


2  

Not to contradict the previous theoretical or mathematical answers, but a Functor is also an Object (in an Object-Oriented programming language) that has only one method and is effectively used as a function.

并不是要与之前的理论或数学答案相矛盾,而是函子也是一个对象(在面向对象编程语言中),它只有一个方法,并且有效地用作函数。

An example is the Runnable interface in Java, which has only one method: run.

Java中的Runnable接口就是一个例子,它只有一个方法:运行。

Consider this example, first in Javascript, which has first-class functions:

考虑这个例子,首先是Javascript,它具有一流的功能:

[1, 2, 5, 10].map(function(x) { return x*x; });

Output: [1, 4, 25, 100]

输出:[1,4,25,100]

The map method takes a function and returns a new array with each element being the result of the application of that function to the value at the same position in the original array.

map方法接受一个函数并返回一个新的数组,每个元素都是该函数应用到原始数组中相同位置的值的结果。

To do the same thing is Java, using a Functor, you would first need to define an interface, say:

要做同样的事情,Java,使用一个函数,你首先需要定义一个接口,说:

public interface IntMapFunction {
  public int f(int x);
}

Then, if you add a collection class which had a map function, you could do:

然后,如果您添加一个具有map函数的集合类,您可以这样做:

myCollection.map(new IntMapFunction() { public int f(int x) { return x * x; } });

This uses an in-line subclass of IntMapFunction to create a Functor, which is the OO equivalent of the function from the earlier JavaScript example.

这使用了IntMapFunction的内联子类来创建一个函数,它与前面的JavaScript示例中的函数的OO等价。

Using Functors let you apply functional techniques in an OO language. Of course, some OO languages also have support for functions directly, so this isn't required.

使用函数符可以在OO语言中应用函数技术。当然,一些OO语言也直接支持函数,所以这不是必需的。

Reference: http://en.wikipedia.org/wiki/Function_object

参考:http://en.wikipedia.org/wiki/Function_object

#13


1  

KISS: A functor is an object that has a map method.

Arrays in JavaScript implement map and are therefore functors. Promises, Streams and Trees often implement map in functional languages, and when they do, they are considered functors. The map method of the functor takes it’s own contents and transforms each of them using the transformation callback passed to map, and returns a new functor, which contains the structure as the first functor, but with the transformed values.

数组在JavaScript中实现映射,因此是函数。承诺、流和树通常在函数语言中实现映射,当它们执行时,它们被认为是函数。函数的map方法获取自己的内容,并使用传递给映射的转换回调对它们进行转换,并返回一个新的函数,该函数包含作为第一个函数的结构,但是带有转换后的值。

src: https://www.youtube.com/watch?v=DisD9ftUyCk&feature=youtu.be&t=76

src:https://www.youtube.com/watch?v=DisD9ftUyCk&feature=youtu.be&t=76

#14


1  

Rough Overview

In functional programming, a functor is essentially a construction of lifting ordinary unary functions (i.e. those with one argument) to functions between variables of new types. It is much easier to write and maintain simple functions between plain objects and use functors to lift them, then to manually write functions between complicated container objects. Further advantage is to write plain functions only once and then re-use them via different functors.

在函数编程中,函数本质上是将普通一元函数(即带一个参数的函数)提升到新类型变量之间的函数。在普通对象之间编写和维护简单函数,并使用函数函数来提升它们,然后在复杂容器对象之间手工编写函数,这样做要容易得多。进一步的优点是只编写一次简单的函数,然后通过不同的函数重新使用它们。

Examples of functors include arrays, "maybe" and "either" functors, futures (see e.g. https://github.com/Avaq/Fluture), and many others.

函数的例子包括数组、“maybe”和“either”函数、futures(参见https://github.com/Avaq/Fluture)和其他许多函数。

Illustration

Consider the function constructing the full person's name from the first and last names. We could define it like fullName(firstName, lastName) as function of two arguments, which however would not be suitable for functors that only deal with functions of one arguments. To remedy, we collect all the arguments in a single object name, which now becomes the function's single argument:

考虑使用从姓和姓构造全名的函数。我们可以将它定义为fullName(firstName, lastName)作为两个参数的函数,但这并不适合只处理一个参数的函数的函数。为了补救,我们将所有参数收集到一个对象名中,现在该对象名成为函数的单个参数:

// In JavaScript notation
fullName = name => name.firstName + ' ' + name.lastName

Now what if we have many people in an array? Instead of manually go over the list, we can simply re-use our function fullName via the map method provided for arrays with short single line of code:

如果数组中有很多人呢?不需要手工检查列表,我们可以简单地通过map方法重新使用函数fullName,该方法提供给具有短的单行代码的数组:

fullNameList = nameList => nameList.map(fullName)

and use it like

和使用它

nameList = [
    {firstName: 'Steve', lastName: 'Jobs'},
    {firstName: 'Bill', lastName: 'Gates'}
]

fullNames = fullNameList(nameList) 
// => ['Steve Jobs', 'Bill Gates']

That will work, whenever every entry in our nameList is an object providing both firstName and lastName properties. But what if some objects don't (or even aren't objects at all)? To avoid the errors and make the code safer, we can wrap our objects into the Maybe type (se e.g. https://sanctuary.js.org/#maybe-type):

当我们的nameList中的每个条目都是提供firstName和lastName属性的对象时,这将起作用。但是如果有些对象没有(甚至根本不是对象)呢?为了避免错误并使代码更安全,我们可以将对象包装到Maybe类型中(例如https://sanctuary.js.org/# Maybe类型):

// function to test name for validity
isValidName = name => 
    (typeof name === 'object') 
    && (typeof name.firstName === 'string')
    && (typeof name.lastName === 'string')

// wrap into the Maybe type
maybeName = name => 
    isValidName(name) ? Just(name) : Nothing()

where Just(name) is a container carrying only valid names and Nothing() is the special value used for everything else. Now instead of interrupting (or forgetting) to check the validity of our arguments, we can simply reuse (lift) our original fullName function with another single line of code, based again on the map method, this time provided for the Maybe type:

其中,Just(name)是只包含有效名称的容器,而Nothing()是用于其他一切的特殊值。现在,我们不需要中断(或忘记)检查参数的有效性,只需使用另一行代码(再次基于map方法)重用原始的全名函数,这一次提供了Maybe类型:

// Maybe Object -> Maybe String
maybeFullName = maybeName => maybeName.map(fullName)

and use it like

和使用它

justSteve = maybeName(
    {firstName: 'Steve', lastName: 'Jobs'}
) // => Just({firstName: 'Steve', lastName: 'Jobs'})

notSteve = maybeName(
    {lastName: 'SomeJobs'}
) // => Nothing()

steveFN = maybeFullName(justSteve)
// => Just('Steve Jobs')

notSteveFN = maybeFullName(notSteve)
// => Nothing()

Category Theory

A Functor in Category Theory is a map between two categories respecting composition of their morphisms. In a Computer Language, the main Category of interest is the one whose objects are types (certain sets of values), and whose morphisms are functions f:a->b from one type a to another type b.

范畴论中的一个函子是两个范畴之间关于它们形态构成的映射。在计算机语言中,感兴趣的主要类别是对象是类型(特定集合的值),而其morphisms是函数f:a->b从a类型到另一种类型b。

For example, take a to be the String type, b the Number type, and f is the function mapping a string into its length:

例如,以a为字符串类型,b为数字类型,f是将字符串映射到其长度的函数:

// f :: String -> Number
f = str => str.length

Here a = String represents the set of all strings and b = Number the set of all numbers. In that sense, both a and b represent objects in the Set Category (which is closely related to the category of types, with the difference being inessential here). In the Set Category, morphisms between two sets are precisely all functions from the first set into the second. So our length function f here is a morphism from the set of strings into the set of numbers.

这里a =字符串表示所有字符串的集合,b =所有数字的集合。从这个意义上说,a和b都表示集合类别中的对象(它与类型类别密切相关,这里的差异并不重要)。在集合类中,两个集合之间的morphisms完全是由第一个集合到第二个集合的所有函数。所以这里的长度函数f是从一组字符串到一组数字的形式。

As we only consider the set category, the relevant Functors from it into itself are maps sending objects to objects and morphisms to morphisms, that satisfy certain algebraic laws.

由于我们只考虑集合的范畴,它的相关函子从它本身就是映射到对象的映射,morphisms到morphisms的映射,满足一定的代数规律。

Example: Array

Array can mean many things, but only one thing is a Functor -- the type construct, mapping a type a into the type [a] of all arrays of type a. For instance, the Array functor maps the type String into the type [String] (the set of all arrays of strings of arbitrary length), and set type Number into the corresponding type [Number] (the set of all arrays of numbers).

数组可以意味着许多事情,但是只有一件事是一个函子——构造类型,类型映射的类型(一)所有数组的类型。例如,数组函子地图类型字符串的类型(字符串)(所有任意长度的字符串数组的集合),和类型数量设置为相应的类型[数字](所有数字数组的集合)。

It is important not to confuse the Functor map

重要的是不要混淆了功能图。

Array :: a => [a]

with a morphism a -> [a]. The functor simply maps (associates) the type a into the type [a] as one thing to another. That each type is actually a set of elements, is of no relevance here. In contrast, a morphism is an actual function between those sets. For instance, there is a natural morphism (function)

具有a ->的形态特征[a]。函子简单地将类型a映射到类型[a]中,作为一个东西映射到另一个。每一种类型实际上是一组元素,在这里没有相关性。与之相反,态则是这些集合之间的实际函数。例如,有一个自然的同态(函数)

pure :: a -> [a]
pure = x => [x]

which sends a value into the 1-element array with that value as single entry. That function is not a part of the Array Functor! From the point of view of this functor, pure is just a function like any other, nothing special.

它将一个值发送到1-element数组中,该值作为单个条目。该函数不是数组函数的一部分!从这个函数的角度来看,纯函数和其他函数一样,没什么特别的。

On the other hand, the Array Functor has its second part -- the morphism part. Which maps a morphism f :: a -> b into a morphism [f] :: [a] -> [b]:

另一方面,阵列函子有它的第二部分——模态部分。将a -> b映射为一个morphism [f]: [a] -> [b]:

// a -> [a]
Array.map(f) = arr => arr.map(f)

Here arr is any array of arbitrary length with values of type a, and arr.map(f) is the array of the same length with values of type b, whose entries are results of applying f to the entries of arr. To make it a functor, the mathematical laws of mapping identity to identity and compositions to compositions must hold, which are easy to check in this Array example.

这里arr是任意长度的数组,类型为a,而arr.map(f)是相同长度的数组,类型为b,其条目是将f应用于arr的条目的结果。要使它成为一个函子,必须具有将恒等映射到恒等和复合映射到复合的数学法则,这在这个数组示例中很容易检查。

#15


-3  

In practice, functor means an object that implements the call operator in C++. In ocaml I think functor refers to something that takes a module as input and output another module.

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

#16


-5  

Put simply, a functor, or function object, is a class object that can be called just like a function.

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

In C++:

在c++中:

This is how you write a function

这就是函数的写法

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

This is how you write a functor

这就是如何写出一个函数

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

Now you can do this:

现在你可以这样做:

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

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

What makes these so great is that you can keep state in the class - imagine if you wanted to ask a function how many times it has been called. There's no way to do this in a neat, encapsulated way. With a function object, it's just like any other class: you'd have some instance variable that you increment in operator () and some method to inspect that variable, and everything's neat as you please.

使它们如此伟大的原因是,您可以在类中保持状态——想象一下,如果您想问一个函数它被调用了多少次。没有办法以一种简洁的、封装的方式来实现这一点。对于函数对象,它就像任何其他类一样:您将在操作符()中增加一个实例变量,并使用一些方法来检查该变量,一切都很整洁。

#17


-9  

Functor is not specifically related to functional programming. It's just a "pointer" to a function or some kind of object, that can be called as it would be a function.

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

#1


251  

The word "functor" comes from category theory, which is a very general, very abstract branch of mathematics. It has been borrowed by designers of functional languages in at least two different ways.

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

  • 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.

    在ML语言家族中,函数器是一个以一个或多个其他模块作为参数的模块。它被认为是一种高级特性,大多数初级程序员都很难使用它。

    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

      键上的total-order函数。

    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.

    ML函数的另一个应用是分层网络协议。链接到CMU Fox集团的一篇很棒的论文;它展示了如何使用函子在更简单的层(如IP层,甚至直接通过以太网)上构建更复杂的协议层(如TCP层)。每一层都被实现为一个函子,以其下面的层作为参数。软件的结构实际上反映了人们思考问题的方式,而不是只存在于程序员头脑中的层。1994年,当这本书出版的时候,是一件大事。

    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.

    对于一个ML函数的野生示例,您可以看到包含可发布的(例如,在工作中函数的例子。对于ML模块系统(与其他类型的模块进行比较)的精彩、清晰、清晰的解释,请阅读Xavier Leroy 1994年的brilliant POPL论文清单类型、模块和单独编译的前几页。

  • 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:

    在Haskell中,在一些相关的纯函数语言中,Functor是一个类型类。类型属于类型类(或者更严格地说,类型是“类型类”的实例),当类型提供具有特定预期行为的某些操作时。如果类型T具有某种类似集合的行为,则它可以属于类函子:

    • 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.

      类型T在另一个类型上被参数化,您应该将其视为集合的元素类型。如果分别包含整数、字符串或布尔值,则完整集合的类型是T Int、T String、T Bool。如果元素类型未知,则将其作为类型参数a写入,如在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.

      示例包括列表(类型a的零或多个元素)、可能类型(类型a的零或一个元素)、类型a的元素集、类型a的元素数组、包含类型a的值的所有搜索树,以及许多您可以想到的其他元素。

    • 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

      T要满足的另一个性质是如果你有一个a - >b类型的函数(一个元素上的函数)那么你必须能够把这个函数和与集合相关的函数乘积。您可以使用操作符fmap来实现这一点,它由Functor类型类中的每个类型共享。运算符实际上是重载的,所以如果你有一个函数,即使类型是Int -> Bool,那么

      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

        将0转换为0,将7转换为False

      In Haskell, this property is expressed by giving the type of fmap:

      在Haskell中,这个属性通过提供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."

      我们现在有一个小t,意思是“函数类中的任何类型”

    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.

    长话短说,在Haskell中,函数是一种集合,如果给你一个关于元素的函数,fmap会给你一个关于集合的函数。正如您可以想象的,这是一个可以被广泛重用的想法,这就是为什么它是Haskell标准库的一部分。

As usual, people continue to invent new, useful abstractions, and you may want to look into applicative functors, for which the best reference may be a paper called Applicative Programming with Effects by Conor McBride and Ross Paterson.

和往常一样,人们不断地发明新的、有用的抽象,您可能想要研究应用函数,其中最好的参考可能是Conor McBride和Ross Paterson所著的《应用程序编程》(applicative Programming)论文。

#2


49  

Other answers here are complete, but I'll try another explanation of the FP use of functor. Take this as analogy:

这里的其他答案是完整的,但是我将尝试另一种关于泛函子使用的解释。把这个类比:

A functor is a container of type a that, when subjected to a function that maps from ab, yields a container of type b.

函子是一种容器类型的,当受到一个函数映射从→b,收益率b型的容器。

Unlike the abstracted-function-pointer use in C++, here the functor is not the function; rather, it's something that behaves consistently when subjected to a function.

与c++中的抽象函数指针不同,这里的函数不是函数;相反,当受到一个函数时,它的行为是一致的。

#3


36  

There are three different meanings, not much related!

有三种不同的含义,没有多少关联!

  • 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)

    在Ocaml中,它是一个参数化的模块。参见手册。我认为探索它们的最好方法是举例:(写得快,可能有错误)

    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);;
    

You can now add quickly many possible orders, ways to form new orders, do a binary or linear search easily over them. Generic programming FTW.

现在,您可以快速添加许多可能的订单,生成新订单的方法,轻松地进行二进制或线性搜索。泛型编程增值。

  • 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.

    在像Haskell这样的函数式编程语言中,它意味着可以“映射”的某些类型构造函数(如列表、集合等参数化类型)。准确地说,一个f函子有(a -> b) -> (f a -> f b),这源于范畴理论。你链接到的*文章就是这个用法。

    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
    

So, this is a special kind of a type constructors, and has little to do with functors in Ocaml!

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

  • In imperative languages, it is a pointer to function.
  • 在命令式语言中,它是指向函数的指针。

#4


15  

In OCaml, it's a parameterised module.

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

If you know C++, think of an OCaml functor as a template. C++ only has class templates, and functors work at the module scale.

如果您知道c++,可以将OCaml函数当作模板。c++只具有类模板,函数符在模块范围内工作。

An example of functor is Map.Make; module StringMap = Map.Make (String);; builds a map module that works with String-keyed maps.

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

You couldn't achieve something like StringMap with just polymorphism; you need to make some assumptions on the keys. The String module contains the operations (comparison, etc) on a totally ordered string type, and the functor will link against the operations the String module contains. You could do something similar with object-oriented programming, but you'd have method indirection overhead.

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

#5


12  

You got quite a few good answers. I'll pitch in:

你得到了不少好答案。我将投入:

A functor, in the mathematical sense, is a special kind of function on an algebra. It is a minimal function which maps an algebra to another algebra. "Minimality" is expressed by the functor laws.

在数学意义上,函数是代数上的一种特殊的函数。它是一个将代数映射到另一个代数的极小函数。“极小”是由函子定律表示的。

There are two ways to look at this. For example, lists are functors over some type. That is, given an algebra over a type 'a', you can generate a compatible algebra of lists containing things of type 'a'. (For example: the map that takes an element to a singleton list containing it: f(a) = [a]) Again, the notion of compatibility is expressed by the functor laws.

有两种方式来看待这个问题。例如,列表是某种类型的函数。也就是说,给定一个关于a类型的代数,您可以生成包含a类型的东西的列表的兼容代数。(例如:将一个元素带到包含它的单例列表的映射:f(a) = [a]))同样,兼容性的概念由函数法则表示。

On the other hand, given a functor f "over" a type a, (that is, f a is the result of applying the functor f to the algebra of type a), and function from g: a -> b, we can compute a new functor F = (fmap g) which maps f a to f b. In short, fmap is the part of F that maps "functor parts" to "functor parts", and g is the part of the function that maps "algebra parts" to "algebra parts". It takes a function, a functor, and once complete, it IS a functor too.

另一方面,鉴于函子f / a型,(也就是说,f是应用函子的结果f的代数a型),并从g函数:a - > b,我们可以计算一个新的函子f =(fmap g)映射f a到f b。简而言之,fmap是f的一部分映射“函子零件”“函子零件”,和g函数的一部分,“代数”映射到“代数部分”。它需要一个函数,一个函数,一旦完成,它也是一个函数。

It might seem that different languages are using different notions of functors, but they're not. They're merely using functors over different algebras. OCamls has an algebra of modules, and functors over that algebra let you attach new declarations to a module in a "compatible" way.

似乎不同的语言使用不同的功能函数,但它们不是。它们只是在不同的代数上使用函子。OCamls有一个模块代数,而该代数上的函数可以让您以“兼容”的方式将新的声明附加到模块上。

A Haskell functor is NOT a type class. It is a data type with a free variable which satisfies the type class. If you're willing to dig into the guts of a datatype (with no free variables), you can reinterpret a data type as a functor over an underlying algebra. For example:

Haskell函数不是类型类。它是一个带有*变量的数据类型,满足类型类。如果您愿意深入研究数据类型的本质(没有*变量),您可以在底层代数中将数据类型重新解释为函数。例如:

data F = F Int

数据F = F Int。

is isomorphic to the class of Ints. So F, as a value constructor, is a function that maps Int to F Int, an equivalent algebra. It is a functor. On the other hand, you don't get fmap for free here. That's what pattern matching is for.

是Ints类的同构。所以F,作为一个值构造函数,是一个将Int映射到F Int的函数,等价的代数。这是一个函子。另一方面,你不能在这里免费获得fmap。这就是模式匹配的作用。

Functors are good for "attaching" things to elements of algebras, in an algebraically compatible way.

函数函数可以很好地以代数相容的方式将东西“附加”到代数的元素中。

#6


7  

There is a pretty good example in the O'Reilly OCaml book that's on Inria's website (which as of writing this is unfortunately down). I found a very similar example in this book used by caltech: Introduction to OCaml (pdf link). The relevant section is the chapter on functors (Page 139 in the book, page 149 in the PDF).

在Inria网站上的O'Reilly OCaml书中有一个很好的例子(不幸的是,在写这本书的时候,它已经被删除了)。我在加州理工学院使用的这本书中发现了一个非常相似的例子:OCaml简介(pdf链接)。相关章节是关于函数者的一章(书139页,PDF页149页)。

In the book they have a functor called MakeSet which creates a data structure that consists of a list, and functions to add an element, determine if an element is in the list, and to find the element. The comparison function that is used to determine if it's in/not in the set has been parametrized (which is what makes MakeSet a functor instead of a module).

在书中,他们有一个名为MakeSet的函数,它创建一个由列表组成的数据结构,以及添加元素的函数,确定元素是否在列表中,并查找元素。用来确定它是否在集合中的比较函数已经被参数化了(这是使MakeSet成为一个函数而不是模块的原因)。

They also have a module that implements the comparison function so that it does a case insensitive string compare.

它们还有一个实现比较函数的模块,以便它执行不区分大小写的字符串比较。

Using the functor and the module that implements the comparison they can create a new module in one line:

使用功能函数和实现比较的模块,可以在一行中创建一个新模块:

module SSet = MakeSet(StringCaseEqual);;

that creates a module for a set data structure that uses case insensitive comparisons. If you wanted to create a set that used case sensitive comparisons then you would just need to implement a new comparison module instead of a new data structure module.

这就为一个用例不敏感比较的set数据结构创建了一个模块。如果您想要创建一个使用区分大小写比较的集合,那么您只需实现一个新的比较模块,而不是一个新的数据结构模块。

Tobu compared functors to templates in C++ which I think is quite apt.

Tobu将函数与c++中的模板进行了比较,我认为这是很合适的。

#7


7  

The best answer to that question is found in "Typeclassopedia" by Brent Yorgey.

这个问题的最佳答案是布兰特·约克吉的《类型学》。

This issue of Monad Reader contain a precise definition of what a functor is as well as many definition of other concepts as well as a diagram. (Monoid, Applicative, Monad and other concept are explained and seen in relation to a functor).

Monad阅读器的这个问题包含了一个函数的精确定义,以及其他概念的定义以及一个图表。(单线、应用、单点和其他概念在与函子的关系中被解释和看到)。

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

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

excerpt from Typeclassopedia for Functor: "A simple intuition is that a Functor represents a “container” of some sort, along with the ability to apply a function uniformly to every element in the container"

摘自Typeclassopedia对于Functor:“一个简单的直觉是:一个函数表示某种“容器”,以及将函数均匀地应用到容器中的每个元素的能力”

But really the whole typeclassopedia is a highly recommended reading that is surprisingly easy. In a way you can see the typeclass presented there as a parallel to design pattern in object in the sense that they give you a vocabulary for given behavior or capability.

但实际上,整部类型学都是高度推荐的阅读材料,非常简单。在某种程度上,您可以看到,在对象中,类型化类与设计模式是并行的,因为它们为给定的行为或能力提供了词汇表。

Cheers

干杯

#8


5  

Here's an article on functors from a programming POV, followed up by more specifically how they surface in programming languages.

这里有一篇关于编程POV中的函子的文章,接着是关于它们在编程语言中的表现形式。

The practical use of a functor is in a monad, and you can find many tutorials on monads if you look for that.

函数的实际使用是在monad中,如果您查找monads,您可以找到很多关于monads的教程。

#9


5  

Given the other answers and what I'm going to post now, I'd say that it's a rather heavily overloaded word, but anyway...

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

For a hint regarding the meaning of the word 'functor' in Haskell, ask GHCi:

要了解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

So, basically, a functor in Haskell is something that can be mapped over. Another way to say it is that a functor is something which can be regarded as a container which can be asked to use a given function to transform the value it contains; thus, for lists, fmap coincides with map, for Maybe, fmap f (Just x) = Just (f x), fmap f Nothing = Nothing etc.

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

The Functor typeclass subsection and the section on Functors, Applicative Functors and Monoids of Learn You a Haskell for Great Good give some examples of where this particular concept is useful. (A summary: lots of places! :-))

函数类型学子节和函数、应用函数和学习Haskell的单类的一节很好地给出了这个特殊概念的一些例子。(总结:很多地方!:-))

Note that any monad can be treated as a functor, and in fact, as Craig Stuntz points out, the most often used functors tend to be monads... OTOH, it is convenient at times to make a type an instance of the Functor typeclass without going to the trouble of making it a Monad. (E.g. in the case of ZipList from Control.Applicative, mentioned on one of the aforementioned pages.)

请注意,任何monad都可以被视为一个函子,事实上,正如Craig Stuntz所指出的,最常用的函子往往是monads…OTOH,有时可以方便地将一个类型创建为一个函数类型类型的实例,而不必麻烦地将其创建为Monad。(例如,在从控制链表的情况下。适用的,上面提到过)

#10


5  

In a comment to the top-voted answer, user Wei Hu asks:

在对投票结果的评论中,用户胡伟问道:

I understand both ML-functors and Haskell-functors, but lack the insight to relate them together. What's the relationship between these two, in a category-theoretical sense?

我理解ML-functors和haskelly -functors,但我没有把它们联系在一起的洞察力。在分类理论意义上,这两者之间的关系是什么?

Note: I don't know ML, so please forgive and correct any related mistakes.

注意:我不知道ML,所以请原谅并改正相关错误。

Let's initially assume that we are all familiar with the definitions of 'category' and 'functor'.

让我们先假设我们都熟悉“category”和“functor”的定义。

A compact answer would be that "Haskell-functors" are (endo-)functors F : Hask -> Hask while "ML-functors" are functors G : ML -> ML'.

一个简洁的答案是“haskelly -functors”(endo-)是F: Hask -> Hask,而“ML- >”是G: ML- > ML的functors。

Here, Hask is the category formed by Haskell types and functions between them, and similarly ML and ML' are categories defined by ML structures.

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

Note: There are some technical issues with making Hask a category, but there are ways around them.

注意:创建Hask有一些技术问题,但是有一些方法可以解决这些问题。

From a category theoretic perspective, this means that a Hask-functor is a map F of Haskell types:

从范畴理论的角度来看,这意味着Hask-functor是Haskell类型的map F:

data F a = ...

along with a map fmap of Haskell functions:

连同Haskell函数的地图fmap:

instance Functor F where
    fmap f = ...

ML is pretty much the same, though there is no canonical fmap abstraction I am aware of, so let's define one:

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

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

That is f maps ML-types and fmap maps ML-functions, so

即f映射ml类型,fmap映射ml函数

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

is a functor F: StructA -> StructB.

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

#11


3  

"Functor is mapping of objects and morphisms that preserves composition and identity of a category."

“函子是对象和形态的映射,保存了一个类别的组成和特征。”

Lets define what is a category ?

让我们定义什么是类别?

It's a bunch of objects!

它是一堆东西!

Draw a few dots (for now 2 dots, one is 'a' another is 'b') inside a circle and name that circle A(Category) for now.

画几个点(现在有两个点,一个是“a”,另一个是“b”)在一个圆里,现在把这个圆命名为a(类别)。

What does the category holds ?

这个类别包含什么?

Composition between objects and Identity function for every object.

对象之间的组合和每个对象的恒等函数。

So, we have to map the objects and preserve the composition after applying our Functor.

因此,我们需要映射对象并在应用函数之后保存合成。

Lets imagine 'A' is our category which has objects ['a', 'b'] and there exists a morphism a -> b

假设“A”是我们的类别,它有对象[A', 'b'],并且存在一个morphism A -> b

Now, we have to define a functor which can map these objects and morphisms into another category 'B'.

现在,我们需要定义一个函数,它可以将这些对象和morphisms映射到另一个类别'B'。

Lets say the functor is called 'Maybe'

假设这个函数叫做" Maybe "

data Maybe a = Nothing | Just a

So, The category 'B' looks like this.

B类是这样的。

Please draw another circle but this time with 'Maybe a' and 'Maybe b' instead of 'a' and 'b'.

请再画一个圆,这次用“也许a”和“也许b”代替“a”和“b”。

Everything seems good and all the objects are mapped

一切看起来都很好,所有的对象都被映射了。

'a' became 'Maybe a' and 'b' became 'Maybe b'.

“a”变成了“也许a”,“b”变成了“也许b”。

But the problem is we have to map the morphism from 'a' to 'b' as well.

但是问题是我们也必须把这个符号从a映射到b。

That means morphism a -> b in 'A' should map to morphism 'Maybe a' -> 'Maybe b'

这意味着a -> b在" a "中应该映射到"可能a " -可能b "

morphism from a -> b is called f, then morphism from 'Maybe a' -> 'Maybe b' is called 'fmap f'

a - >b的morphism被称为f,而'Maybe a' -> 'Maybe b'的morphism被称为'fmap f'

Now lets see what function 'f' was doing in 'A' and see if we can replicate it in 'B'

现在我们来看看函数f在A中的作用看看能否在B中复制它

function definition of 'f' in 'A':

f在A中的函数定义:

f :: a -> b

f takes a and returns b

f取a,返回b

function definition of 'f' in 'B' :

f在B中的函数定义:

f :: Maybe a -> Maybe b

f takes Maybe a and return Maybe b

f取a,返回b

lets see how to use fmap to map the function 'f' from 'A' to function 'fmap f' in 'B'

让我们看看如何使用fmap将函数f从A映射到B的fmap f

definition of fmap

fmap的定义

fmap :: (a -> b) -> (Maybe a -> Maybe b)
fmap f Nothing = Nothing
fmap f (Just x) = Just(f x)

So, what are we doing here ?

那么,我们在这里做什么呢?

We are applying the function 'f' to 'x' which is of type 'a'. Special pattern matching of 'Nothing' comes from the definition of Functor Maybe.

我们将函数f应用到x,类型为a。“无”的特殊模式匹配可能来自于函子的定义。

So, we mapped our objects [a, b] and morphisms [ f ] from category 'A' to category 'B'.

因此,我们将我们的对象(a, b)和morphisms [f]从类别a映射到类别b。

Thats Functor!

这函子!

在函数式编程中,什么是函子?

#12


2  

Not to contradict the previous theoretical or mathematical answers, but a Functor is also an Object (in an Object-Oriented programming language) that has only one method and is effectively used as a function.

并不是要与之前的理论或数学答案相矛盾,而是函子也是一个对象(在面向对象编程语言中),它只有一个方法,并且有效地用作函数。

An example is the Runnable interface in Java, which has only one method: run.

Java中的Runnable接口就是一个例子,它只有一个方法:运行。

Consider this example, first in Javascript, which has first-class functions:

考虑这个例子,首先是Javascript,它具有一流的功能:

[1, 2, 5, 10].map(function(x) { return x*x; });

Output: [1, 4, 25, 100]

输出:[1,4,25,100]

The map method takes a function and returns a new array with each element being the result of the application of that function to the value at the same position in the original array.

map方法接受一个函数并返回一个新的数组,每个元素都是该函数应用到原始数组中相同位置的值的结果。

To do the same thing is Java, using a Functor, you would first need to define an interface, say:

要做同样的事情,Java,使用一个函数,你首先需要定义一个接口,说:

public interface IntMapFunction {
  public int f(int x);
}

Then, if you add a collection class which had a map function, you could do:

然后,如果您添加一个具有map函数的集合类,您可以这样做:

myCollection.map(new IntMapFunction() { public int f(int x) { return x * x; } });

This uses an in-line subclass of IntMapFunction to create a Functor, which is the OO equivalent of the function from the earlier JavaScript example.

这使用了IntMapFunction的内联子类来创建一个函数,它与前面的JavaScript示例中的函数的OO等价。

Using Functors let you apply functional techniques in an OO language. Of course, some OO languages also have support for functions directly, so this isn't required.

使用函数符可以在OO语言中应用函数技术。当然,一些OO语言也直接支持函数,所以这不是必需的。

Reference: http://en.wikipedia.org/wiki/Function_object

参考:http://en.wikipedia.org/wiki/Function_object

#13


1  

KISS: A functor is an object that has a map method.

Arrays in JavaScript implement map and are therefore functors. Promises, Streams and Trees often implement map in functional languages, and when they do, they are considered functors. The map method of the functor takes it’s own contents and transforms each of them using the transformation callback passed to map, and returns a new functor, which contains the structure as the first functor, but with the transformed values.

数组在JavaScript中实现映射,因此是函数。承诺、流和树通常在函数语言中实现映射,当它们执行时,它们被认为是函数。函数的map方法获取自己的内容,并使用传递给映射的转换回调对它们进行转换,并返回一个新的函数,该函数包含作为第一个函数的结构,但是带有转换后的值。

src: https://www.youtube.com/watch?v=DisD9ftUyCk&feature=youtu.be&t=76

src:https://www.youtube.com/watch?v=DisD9ftUyCk&feature=youtu.be&t=76

#14


1  

Rough Overview

In functional programming, a functor is essentially a construction of lifting ordinary unary functions (i.e. those with one argument) to functions between variables of new types. It is much easier to write and maintain simple functions between plain objects and use functors to lift them, then to manually write functions between complicated container objects. Further advantage is to write plain functions only once and then re-use them via different functors.

在函数编程中,函数本质上是将普通一元函数(即带一个参数的函数)提升到新类型变量之间的函数。在普通对象之间编写和维护简单函数,并使用函数函数来提升它们,然后在复杂容器对象之间手工编写函数,这样做要容易得多。进一步的优点是只编写一次简单的函数,然后通过不同的函数重新使用它们。

Examples of functors include arrays, "maybe" and "either" functors, futures (see e.g. https://github.com/Avaq/Fluture), and many others.

函数的例子包括数组、“maybe”和“either”函数、futures(参见https://github.com/Avaq/Fluture)和其他许多函数。

Illustration

Consider the function constructing the full person's name from the first and last names. We could define it like fullName(firstName, lastName) as function of two arguments, which however would not be suitable for functors that only deal with functions of one arguments. To remedy, we collect all the arguments in a single object name, which now becomes the function's single argument:

考虑使用从姓和姓构造全名的函数。我们可以将它定义为fullName(firstName, lastName)作为两个参数的函数,但这并不适合只处理一个参数的函数的函数。为了补救,我们将所有参数收集到一个对象名中,现在该对象名成为函数的单个参数:

// In JavaScript notation
fullName = name => name.firstName + ' ' + name.lastName

Now what if we have many people in an array? Instead of manually go over the list, we can simply re-use our function fullName via the map method provided for arrays with short single line of code:

如果数组中有很多人呢?不需要手工检查列表,我们可以简单地通过map方法重新使用函数fullName,该方法提供给具有短的单行代码的数组:

fullNameList = nameList => nameList.map(fullName)

and use it like

和使用它

nameList = [
    {firstName: 'Steve', lastName: 'Jobs'},
    {firstName: 'Bill', lastName: 'Gates'}
]

fullNames = fullNameList(nameList) 
// => ['Steve Jobs', 'Bill Gates']

That will work, whenever every entry in our nameList is an object providing both firstName and lastName properties. But what if some objects don't (or even aren't objects at all)? To avoid the errors and make the code safer, we can wrap our objects into the Maybe type (se e.g. https://sanctuary.js.org/#maybe-type):

当我们的nameList中的每个条目都是提供firstName和lastName属性的对象时,这将起作用。但是如果有些对象没有(甚至根本不是对象)呢?为了避免错误并使代码更安全,我们可以将对象包装到Maybe类型中(例如https://sanctuary.js.org/# Maybe类型):

// function to test name for validity
isValidName = name => 
    (typeof name === 'object') 
    && (typeof name.firstName === 'string')
    && (typeof name.lastName === 'string')

// wrap into the Maybe type
maybeName = name => 
    isValidName(name) ? Just(name) : Nothing()

where Just(name) is a container carrying only valid names and Nothing() is the special value used for everything else. Now instead of interrupting (or forgetting) to check the validity of our arguments, we can simply reuse (lift) our original fullName function with another single line of code, based again on the map method, this time provided for the Maybe type:

其中,Just(name)是只包含有效名称的容器,而Nothing()是用于其他一切的特殊值。现在,我们不需要中断(或忘记)检查参数的有效性,只需使用另一行代码(再次基于map方法)重用原始的全名函数,这一次提供了Maybe类型:

// Maybe Object -> Maybe String
maybeFullName = maybeName => maybeName.map(fullName)

and use it like

和使用它

justSteve = maybeName(
    {firstName: 'Steve', lastName: 'Jobs'}
) // => Just({firstName: 'Steve', lastName: 'Jobs'})

notSteve = maybeName(
    {lastName: 'SomeJobs'}
) // => Nothing()

steveFN = maybeFullName(justSteve)
// => Just('Steve Jobs')

notSteveFN = maybeFullName(notSteve)
// => Nothing()

Category Theory

A Functor in Category Theory is a map between two categories respecting composition of their morphisms. In a Computer Language, the main Category of interest is the one whose objects are types (certain sets of values), and whose morphisms are functions f:a->b from one type a to another type b.

范畴论中的一个函子是两个范畴之间关于它们形态构成的映射。在计算机语言中,感兴趣的主要类别是对象是类型(特定集合的值),而其morphisms是函数f:a->b从a类型到另一种类型b。

For example, take a to be the String type, b the Number type, and f is the function mapping a string into its length:

例如,以a为字符串类型,b为数字类型,f是将字符串映射到其长度的函数:

// f :: String -> Number
f = str => str.length

Here a = String represents the set of all strings and b = Number the set of all numbers. In that sense, both a and b represent objects in the Set Category (which is closely related to the category of types, with the difference being inessential here). In the Set Category, morphisms between two sets are precisely all functions from the first set into the second. So our length function f here is a morphism from the set of strings into the set of numbers.

这里a =字符串表示所有字符串的集合,b =所有数字的集合。从这个意义上说,a和b都表示集合类别中的对象(它与类型类别密切相关,这里的差异并不重要)。在集合类中,两个集合之间的morphisms完全是由第一个集合到第二个集合的所有函数。所以这里的长度函数f是从一组字符串到一组数字的形式。

As we only consider the set category, the relevant Functors from it into itself are maps sending objects to objects and morphisms to morphisms, that satisfy certain algebraic laws.

由于我们只考虑集合的范畴,它的相关函子从它本身就是映射到对象的映射,morphisms到morphisms的映射,满足一定的代数规律。

Example: Array

Array can mean many things, but only one thing is a Functor -- the type construct, mapping a type a into the type [a] of all arrays of type a. For instance, the Array functor maps the type String into the type [String] (the set of all arrays of strings of arbitrary length), and set type Number into the corresponding type [Number] (the set of all arrays of numbers).

数组可以意味着许多事情,但是只有一件事是一个函子——构造类型,类型映射的类型(一)所有数组的类型。例如,数组函子地图类型字符串的类型(字符串)(所有任意长度的字符串数组的集合),和类型数量设置为相应的类型[数字](所有数字数组的集合)。

It is important not to confuse the Functor map

重要的是不要混淆了功能图。

Array :: a => [a]

with a morphism a -> [a]. The functor simply maps (associates) the type a into the type [a] as one thing to another. That each type is actually a set of elements, is of no relevance here. In contrast, a morphism is an actual function between those sets. For instance, there is a natural morphism (function)

具有a ->的形态特征[a]。函子简单地将类型a映射到类型[a]中,作为一个东西映射到另一个。每一种类型实际上是一组元素,在这里没有相关性。与之相反,态则是这些集合之间的实际函数。例如,有一个自然的同态(函数)

pure :: a -> [a]
pure = x => [x]

which sends a value into the 1-element array with that value as single entry. That function is not a part of the Array Functor! From the point of view of this functor, pure is just a function like any other, nothing special.

它将一个值发送到1-element数组中,该值作为单个条目。该函数不是数组函数的一部分!从这个函数的角度来看,纯函数和其他函数一样,没什么特别的。

On the other hand, the Array Functor has its second part -- the morphism part. Which maps a morphism f :: a -> b into a morphism [f] :: [a] -> [b]:

另一方面,阵列函子有它的第二部分——模态部分。将a -> b映射为一个morphism [f]: [a] -> [b]:

// a -> [a]
Array.map(f) = arr => arr.map(f)

Here arr is any array of arbitrary length with values of type a, and arr.map(f) is the array of the same length with values of type b, whose entries are results of applying f to the entries of arr. To make it a functor, the mathematical laws of mapping identity to identity and compositions to compositions must hold, which are easy to check in this Array example.

这里arr是任意长度的数组,类型为a,而arr.map(f)是相同长度的数组,类型为b,其条目是将f应用于arr的条目的结果。要使它成为一个函子,必须具有将恒等映射到恒等和复合映射到复合的数学法则,这在这个数组示例中很容易检查。

#15


-3  

In practice, functor means an object that implements the call operator in C++. In ocaml I think functor refers to something that takes a module as input and output another module.

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

#16


-5  

Put simply, a functor, or function object, is a class object that can be called just like a function.

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

In C++:

在c++中:

This is how you write a function

这就是函数的写法

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

This is how you write a functor

这就是如何写出一个函数

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

Now you can do this:

现在你可以这样做:

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

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

What makes these so great is that you can keep state in the class - imagine if you wanted to ask a function how many times it has been called. There's no way to do this in a neat, encapsulated way. With a function object, it's just like any other class: you'd have some instance variable that you increment in operator () and some method to inspect that variable, and everything's neat as you please.

使它们如此伟大的原因是,您可以在类中保持状态——想象一下,如果您想问一个函数它被调用了多少次。没有办法以一种简洁的、封装的方式来实现这一点。对于函数对象,它就像任何其他类一样:您将在操作符()中增加一个实例变量,并使用一些方法来检查该变量,一切都很整洁。

#17


-9  

Functor is not specifically related to functional programming. It's just a "pointer" to a function or some kind of object, that can be called as it would be a function.

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