Что такое функтор в функциональном программировании?

Я сталкивался с термином "функтор" несколько раз, читая различные статьи о функциональном программировании, но авторы обычно предполагают, что читатель уже понимает этот термин. Просмотр в интернете предоставил либо чрезмерно технические описания (см. статья в Википедии) или невероятно расплывчатые описания (см. раздел о Функторах на этом ocaml-учебник веб-сайт).

может кто-то любезно определить термин, объяснить его использование, и, возможно, приведем пример того, как создаются и используются функторы?

редактировать: хотя меня интересует теория, стоящая за этим термином, меня меньше интересует теория, чем реализация и практическое использование концепции.

Изменить 2: похоже, что происходит какая-то кросс-терминолигия: я конкретно имею в виду функторы функционального программирования, а не функциональные объекты c++.

17 ответов


слово "функтор" происходит от теории категорий, которая является очень общей, очень абстрактной ветвью математики. Он был заимствован дизайнерами функциональных языков, по крайней мере, двумя различными способами.

  • в семействе языков ML функтор-это модуль, который принимает один или несколько других модулей в качестве параметра. Это считается передовой функцией, и большинство начинающих программистов испытывают с ней трудности.

    в качестве примера реализация и практическое использование, вы можете определить свою любимую форму сбалансированного бинарного дерева поиска раз и навсегда как функтор, и он будет принимать в качестве параметра модуль, который обеспечивает:

    • тип ключа, который будет использоваться в двоичном дереве

    • функция total-ordering на клавишах

    как только вы это сделаете, вы можете использовать одну и ту же сбалансированную реализацию двоичного дерева навсегда. (Тип значения, хранящегося в дерево обычно остается полиморфным-дереву не нужно смотреть на значения, кроме как копировать их, тогда как дерево определенно должно иметь возможность сравнивать ключи, и оно получает функцию сравнения из параметра функтора.)

    другое применение функторов ML является многоуровневые сетевые протоколы. Ссылка на действительно потрясающую статью группы CMU Fox; она показывает, как использовать функторы для создания более сложных слоев протокола (например, TCP) по типу более простого слои (например, IP или даже непосредственно через Ethernet). Каждый слой реализован как функтор, который принимает в качестве параметра слой под ним. Структура программного обеспечения фактически отражает то, как люди думают о проблеме, в отличие от слоев, существующих только в уме программиста. В 1994 году, когда эта работа была опубликована, это было большое дело.

    для дикого примера функторов ML в действии вы можете увидеть бумагу ML модуль мания, который содержит публикуемый (т. е. страшный) пример функторов на работе. Для блестящего, ясного, прозрачного объяснения системы модулей ML (с сравнениями с другими видами модулей) прочитайте первые несколько страниц блестящей статьи 1994 POPL Ксавье Лероя типы манифестов, модули и отдельная компиляция.

  • в Haskell, и в некотором родственном чисто функциональном языке,Functor это тип class. Тип принадлежит классу type (или более технически тип "является экземпляром" класса type), когда тип предоставляет определенные операции с определенным ожидаемым поведением. Тип T может принадлежать к классу Functor если он имеет определенный набор поведения:

    • тип T параметризуется над другим типом, который вы должны рассматривать как тип элемента коллекции. Тип полной коллекции тогда что-то вроде T Int, T String, T Bool, если вы содержите целые числа, строки или логические значения соответственно. Если тип элемента неизвестен, он записывается как параметр типа a, а в T a.

      примеры включают списки (ноль или более элементов типа a), то Maybe type (ноль или один элемент типа a), комплекта элементов типа a, массив элементов типа a, все виды деревьев поиска, содержащих значения типа a, и многие другие вы можете думать из.

    • другое свойство, которое T должен удовлетворять, что если у вас есть функция типа a -> b (функция на элементах), тогда вы должны иметь возможность взять эту функцию и продукт связанной функции на коллекциях. Вы делаете это с помощью оператора fmap, который разделяется каждым типом в Functor тип класса. Оператор фактически перегружен, поэтому, если у вас есть функция even С типом Int -> Bool, потом

      fmap even
      

      - это перегруженная функция, которая может сделать много замечательных вещей:

      • преобразовать список целых чисел в список логических

      • преобразовать дерево целых чисел в дерево булевых

      • преобразование Nothing to Nothing и Just 7 to Just False

      в Haskell это свойство выражается путем указания типа fmap:

      fmap :: (Functor t) => (a -> b) -> t a -> t b
      

      где у нас теперь есть маленький t, что означает " любой тип в Functor класса."

    короче говоря, в Хаскелле функтор-это своего рода коллекцию, для которой, если вам дана функция на элементах, fmap вернет вам функцию на коллекции. Как вы можете себе представить, эта идея может быть широко использована повторно, поэтому она благословлена как часть стандартной библиотеки Haskell.

как обычно, люди продолжают изобретать новые, полезные абстракции, и вы можете посмотреть в applicative функторы, для которых лучшей ссылкой может быть бумага под названием прикладное программирование с эффектами Конор Макбрайд и Росс Патерсон.


другие ответы здесь завершены, но я попробую другое объяснение использования FP функтор. Возьмите это как аналогию:

функтор-это контейнер типа a это, когда подвергается функции, которая отображает из ab, дает контейнер типа b.

в отличие от абстрагированного-функции-указатель использовать в C++, здесь функтор-это не функция; скорее, это что - то, что ведет себя последовательно, когда подвергнут функция.


есть три разных значения, не так много связанных!

  • в Ocaml это параметризованный модуль. См.руководство. Я думаю, что лучший способ grok их на примере: (написано быстро, может быть багги)

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

теперь вы можете быстро добавить много возможных заказов, способы формирования новых заказов, сделать бинарный или линейный поиск легко над ними. Обобщенное программирование приборов.

  • в функциональном программировании такие языки, как 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
    

Итак, это особый вид конструкторов типов и имеет мало общего с функторами в Ocaml!

  • в императивных языках это указатель на функция.

в OCaml это параметризованный модуль.

Если вы знаете C++, подумайте о функторе OCaml как о шаблоне. C++ имеет только шаблоны классов, а функторы работают в масштабе модуля.

примером функтора является Map.Сделайте;module StringMap = Map.Make (String);; создает модуль карты, который работает со строковыми картами.

вы не могли бы достичь чего-то вроде StringMap только с полиморфизмом; вам нужно сделать некоторые предположения о ключах. Модуль String содержит операции (сравнение, etc) на полностью упорядоченном строковом типе, и функтор будет связываться с операциями, содержащимися в строковом модуле. Вы можете сделать что-то подобное с объектно-ориентированным программированием, но у вас будут накладные расходы метода.


У вас есть довольно много хороших ответов. Я вставлю:

функтор в математическом смысле является специальным видом функции на алгебре. Это минимальная функция, которая сопоставляет алгебру с другой алгеброй. "Минимальность" выражается законами функтора.

есть два способа смотреть на это. Например, списки являются функторами над некоторым типом. То есть, учитывая алгебру над типом "a" , вы можете создать совместимую алгебру списков, содержащих вещи типа "а". (Например: карта, которая принимает элемент в одноэлементный список, содержащий его: f (a) = [a]) опять же, понятие совместимости выражается законами функтора.

с другой стороны, учитывая функтор f "над" типом a (то есть f a является результатом применения функтора f к алгебре типа a) и функции от g: a -> b, мы можем вычислить новый функтор F = (fmap g), который отображает f a на f b. Короче говоря, fmap является частью F, которая сопоставляет "части функтора" с "частями функтора", и g-часть функции, которая отображает "части алгебры"на" части алгебры". Он принимает функцию, функтор, и после завершения он также является функтором.

может показаться, что разные языки используют разные понятия функторов, но это не так. Они просто используют функторы над различными алгебрами. OCamls имеет алгебру модулей, а функторы над этой алгеброй позволяют присоединять новые объявления к модулю "совместимым" способом.

функтор Хаскелл не тип класса. Это тип данных со свободной переменной, которая удовлетворяет класс тип. Если вы готовы копаться в кишках типа данных (без свободных переменных), вы можете переинтерпретировать тип данных как функтор над базовой алгеброй. Например:

данные F = F Int

изоморфно классу Ints. Таким образом, F, как конструктор значений, является функцией, которая отображает Int в F Int, эквивалентную алгебру. Это функтор. С другой стороны, вы не получаете fmap бесплатно здесь. Вот для чего нужно сопоставление.

функторы хороши для" прикрепления " вещей к элементам алгебр алгебраически совместимым способом.


есть довольно хороший пример в книге O'Reilly OCaml, которая находится на веб-сайте Inria (который на момент написания этого, к сожалению, вниз). Я нашел очень похожий пример в этой книге, используемой caltech: введение в OCaml (ссылка pdf). Соответствующий раздел-глава о функторах (страница 139 в книге, страница 149 в PDF).

в книге у них есть функтор под названием MakeSet, который создает структуру данных, состоящую из списка, и функций для добавления элемент, определить, если элемент находится в списке, и найти элемент. Функция сравнения, которая используется для определения, находится ли она в/не в наборе, была параметризована (что делает MakeSet функтором вместо модуля).

у них также есть модуль, который реализует функцию сравнения, так что он делает сравнение строки без учета регистра.

используя функтор и модуль, реализующий сравнение, они могут создать новый модуль в одном строка:

module SSet = MakeSet(StringCaseEqual);;

это создает модуль для структуры данных набора, который использует сравнения без учета регистра. Если вы хотите создать набор, который использует сравнения с учетом регистра, вам просто нужно будет реализовать новый модуль сравнения вместо нового модуля структуры данных.

Tobu сравнил функторы с шаблонами в C++ , которые я думаю, вполне уместны.


лучший ответ на этот вопрос можно найти в "Typeclassopedia" Брента Йорги.

этот выпуск Monad Reader содержит точное определение того, что такое функтор, а также многие определения других понятий, а также диаграмму. (Моноид, Аппликатив, Монада и другое понятие объясняются и рассматриваются по отношению к функтору).

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

выдержка из Typeclassopedia для функтора: "Ля простая интуиция заключается в том, что функтор представляет собой "контейнер" некоторых сортировка, а также возможность применять функцию равномерно к каждому элементу в контейнер"

но на самом деле вся typeclassopedia-это очень рекомендуемое чтение, которое удивительно легко. В некотором смысле вы можете видеть представленный там тип как параллель шаблону дизайна в объекте в том смысле, что они дают вам словарь для данного поведения или способности.

Ура


здесь статья о функторах из POV программирования, а затем более конкретно как они появляются в языках программирования.

практическое использование функтора находится в монаде, и вы можете найти много учебников по монадам, если вы ищете это.


учитывая другие ответы и то, что я собираюсь опубликовать сейчас, я бы сказал, что это довольно перегруженное слово, но в любом случае...

для подсказки относительно значения слова "функтор" в Haskell, спросите 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, for Maybe, fmap f (Just x) = Just (f x), fmap f Nothing = Nothing etc.

функтор typeclass подраздел и раздел функторы, аппликативные функторы и моноиды of узнать вас Haskell для большого добра приведите несколько примеров, где эта концепция полезна. (Резюме: много мест! : -))

обратите внимание, что любая монада может рассматриваться как функтор, и на самом деле, как указывает Крейг станц, наиболее часто используемые функторы, как правило, монады... OTOH, иногда удобно сделать тип экземпляром класса Functor typeclass, не потрудившись сделать его монадой. (Например. в случае ZipList С Control.Applicative, упомянули о одна из вышеупомянутых страниц.)


в комментарии к началу голосования ответ, Вэй Ху спрашивает:

Я понимаю как ML-функторы, так и Haskell-функторы, но не хватает понимание, чтобы связать их вместе. Какова связь между этими во-вторых, в теоретическом смысле?

Примечание: я не знаю ML, поэтому, пожалуйста, простите и исправьте любые связанные ошибки.

давайте сначала предположим, что мы все знаком с определениями "категории" и "функтора".

компактный ответ будет заключаться в том, что" Haskell-функторы " являются (Эндо -) функторами F : Hask -> Hask в то время как" ML-функторы " являются функторами G : ML -> ML'.

здесь Hask - это категория, образованная типами и функциями Haskell между ними, и аналогично ML и ML' категории, определенные структурами ML.

Примечание: есть технические вопросы С Hask a категории, но есть способы обойти их.

С теоретико-категориальной точки зрения это означает, что Hask-функтор карта F типов Haskell:

data F a = ...

вместе с картой fmap функций Haskell:

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.


"функтор-это отображение объектов и морфизмов, которое сохраняет состав и идентичность категории."

определим что такое категория ?

это куча предметов!

нарисуйте несколько точек (на данный момент 2 точки, одна - "a", другая - "b") внутри a круг и назовите этот круг A (категория) на данный момент.

что содержит категория ?

состав между объектами и функцией идентификации для каждый объект.

Итак, мы должны сопоставить объекты и сохранить композицию после применения нашего функтора.

давайте представим ,что " A " - это наша категория, которая имеет объекты ["a", "b"], и существует морфизм a - > b

теперь мы должны определить функтор, который может отображать эти объекты и морфизмы в другую категорию "B".

допустим, функтор называется "может быть"

data Maybe a = Nothing | Just a

Итак, категория " B " выглядит так.

пожалуйста, нарисуйте еще один круг, но на этот раз с "возможно a" и "возможно b" вместо " a " и "b".

все кажется хорошим, и все объекты отображаются

'а' стал 'может' и 'B' стал 'может быть'.

но проблема в том, что мы должны сопоставить морфизм от " a " до "b".

это означает, что морфизм a - > b в " A "должен соответствовать морфизму" возможно a "- > "возможно b"

морфизм из a - > b называется f, затем морфизм из "Возможно a" - > "возможно b" называется "fmap f"

теперь давайте посмотрим, какая функция " f "делала в" A "и посмотрим, сможем ли мы воспроизвести ее в "B"

определение функции "f" в "A":

f :: a -> b

f берет a и возвращает b

определение функции "f" в "B":

f :: Maybe a -> Maybe b

f берет, может быть, a и возвращает, может быть, b

давайте посмотрим, как использовать fmap для отображения функции " f " из " A "в функцию" fmap f " в "B"

определение из fmap

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

Итак, что мы здесь делаем ?

мы применяем функцию " f " к "x", которая имеет тип "a". Специальный шаблон соответствия "ничего" происходит от определения Functor Maybe.

Итак, мы сопоставили наши объекты [a, b] и морфизмы [ f ] из категории " A "в категорию "B".

Функтор Это!

enter image description here


чтобы не противоречить предыдущим теоретическим или математическим ответам, но функтор также является объектом (на объектно-ориентированном языке программирования), который имеет только один метод и эффективно используется в качестве функции.

примером является интерфейс Runnable в Java, который имеет только один метод: run.

рассмотрим этот пример, сначала в Javascript, который имеет первоклассные функции:

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

выход: [1, 4, 25, 100]

метод map принимает функция и возвращает новый массив, каждый элемент которого является результатом применения этой функции к значению в той же позиции в исходном массиве.

чтобы сделать то же самое, Java, используя функтор, вам сначала нужно будет определить интерфейс, скажем:

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

затем, если вы добавите класс коллекции, который имел функцию карты, вы можете сделать:

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

Это использует встроенный подкласс IntMapFunction для создания функтора, который является OO эквивалент функции из более раннего примера JavaScript.

использование функторов позволяет применять функциональные методы на языке OO. Конечно, некоторые языки OO также поддерживают функции напрямую, поэтому это не требуется.

ссылка:http://en.wikipedia.org/wiki/Function_object


Грубый Обзор

в функциональном программировании a функтор по существу является конструкцией подъема обычных унарный функции (т. е. с одним аргументом) функции между переменными новых типов. Гораздо проще писать и поддерживать простые функции между простыми объектами и использовать функторы для их подъема, а затем вручную записывать функции между сложными объектами контейнера. Дальнейшее преимущество-писать простые функции только один раз а затем повторно использовать их через различные функторы.

примеры функторов включают массивы," возможно "и" либо " функторы, фьючерсы (см., например,https://github.com/Avaq/Fluture) и многие другие.

иллюстрации

рассмотрим функцию построения полного имени человека из имени и фамилии. Мы могли бы определить его как fullName(firstName, lastName) как функция двух аргументов, которые, однако, не подходят для функторов, которые имеют дело только с функции одного аргумента. Чтобы исправить, мы собираем все аргументы в одном объекте name, который теперь становится единственным аргументом функции:

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

теперь, что, если у нас много людей в массиве? Вместо того, чтобы вручную перейти по списку, мы можем просто повторно использовать нашу функцию fullName через map метод, предусмотренный для массивов с короткой одной строкой кода:

fullNameList = nameList => nameList.map(fullName)

и использовать его как

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

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

это будет работать, когда каждая запись в наших nameList является объектом обеспечения как firstName и lastName свойства. Но что, если некоторые объекты не являются (или даже не являются объектами вообще)? Чтобы избежать ошибок и сделать код более безопасным, мы можем обернуть наши объекты в Maybe тип (se например https://sanctuary.js.org/#maybe-type):

// 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()

здесь Just(name) - это контейнер, содержащий только действительные имена и Nothing() - это специальное значение, используемое для всего остального. Теперь вместо того, чтобы прерывать (или забывать), чтобы проверить обоснованность наших аргументов, мы можем просто повторно использовать (поднять) наш оригинал fullName функция с другой одной строкой кода, основанной снова на map метод, на этот раз предусмотренный для типа Maybe:

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

и использовать его как

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

Теория Категорий

A функтор на Теория Категорий является картой между двумя категориями, уважающей состав их морфизмов. В Язык, в основная категория интересов-та, у которой объекты are типы (определенные наборы значений), и чьи морфизмы функции f:a->b из одного типа a другой тип b.

например, взять a быть String тип, b тип номера, и f функция, отображающая строку в ее длину:

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

здесь a = String представляет набор всех строк и b = Number в набор всех чисел. В этом смысле оба!--23--> и b представлять объекты в Настройка Категории (который тесно связан с категорией типов, с разницей, несущественной здесь). В категории Set морфизмы между двумя наборами точно все функции из первой группы во вторую. Таким образом, наша функция длины f вот морфизм из множества строк в множество чисел.

как мы рассматриваем только набор категория, соответствующая функторы из него в себя являются карты, отправляющие объекты объектам и морфизмы морфизмам, которые удовлетворяют определенным алгебраическим законам.

пример: Array

Array может означать много вещей, но только одна вещь-функтор-конструкция типа, отображающая тип a в типа [a] всех массивов типа a. Например,Array функтор отображает тип String в типа [String] (набор все массивы строк произвольной длины) и установить тип Number в соответствующий тип [Number] (набор всех массивов чисел).

важно не путать функтор map

Array :: a => [a]

с морфизм a -> [a]. Функтор просто отображает (связывает) тип a в типа [a] как одно к другому. То, что каждый тип на самом деле является набором элементов, здесь не имеет значения. Напротив, морфизм-это фактическая функция между этот набор. Например, существует естественный морфизм (функция)

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

который отправляет значение в массив 1-element с этим значением в виде одной записи. Эта функция не часть Array функтор! С точки зрения этого функтора, pure это просто функция, как и любая другая, ничего особенного.

с другой стороны,Array функтор имеет свою вторую часть-часть морфизма. Который отображает морфизм f :: a -> b в морфизм [f] :: [a] -> [b]:

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

здесь arr - это любой массив произвольной длины со значениями типа a и arr.map(f) - массив одинаковой длины со значениями типа b, чьи записи являются результатами применения f в записи arr. Чтобы сделать его функтором, должны выполняться математические законы отображения тождества на тождество и композиции на композиции, которые легко проверить в этом Array пример.


KISS: функтор-это объект, который имеет метод map.

массивы в JavaScript реализуют map и поэтому являются функторами. Обещания, потоки и деревья часто реализуют map на функциональных языках, и когда они это делают, они считаются функторами. Метод map функтора принимает собственное содержимое и преобразует каждый из них с помощью обратного вызова преобразования, переданного map, и возвращает новый функтор, который содержит структуру в качестве первого функтора, но с преобразованным ценности.

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


на практике functor означает объект, реализующий оператор вызова в C++. В ocaml я думаю, что функтор относится к чему-то, что принимает модуль в качестве ввода и вывода другого модуля.


проще говоря, функтор или объект функции - это объект класса, который можно вызвать так же, как функцию.

В 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!

что делает их настолько великими, что вы можете сохранить состояние в классе-представьте, если вы хотите спросить функцию, сколько раз она была вызвана. Нет способа сделать это в аккуратный, инкапсулированный способ. С объектом function это так же, как и любой другой класс: у вас будет некоторая переменная экземпляра, которую вы увеличиваете в operator () и какой-то метод для проверки этой переменной, и все аккуратно, как вам нравится.


функтор не связан конкретно с функциональным программированием. Это просто "указатель" на функцию или какой-то объект, который можно назвать функцией.