Question

Je suis venu à travers le terme « Functor » à quelques reprises lors de la lecture de divers articles sur la programmation fonctionnelle, mais les auteurs supposent généralement le lecteur comprend déjà le terme. En regardant autour sur le web a fourni soit des descriptions trop techniques (voir Wikipedia article ) ou des descriptions très vagues (voir la section sur foncteurs à ce site OCaml-tutorial ).

Quelqu'un peut-il définir le terme de bien vouloir, expliquer son utilisation, et peut-être donner un exemple de la façon dont Foncteurs sont créés et utilisés?

Modifier :. Même si je suis intéressé par la théorie derrière le terme, je suis moins intéressé par la théorie que je suis dans l'utilisation et la mise en œuvre pratique du concept

Edit 2 : On dirait qu'il ya une croix-terminoligy passe: Je fais référence aux Foncteurs de la programmation fonctionnelle, et non les objets de fonction de C ++

.
Était-ce utile?

La solution

Le mot « foncteur » vient de la théorie des catégories, ce qui est une, branche très abstraite des mathématiques très général. Il a été emprunté par les concepteurs de langages fonctionnels dans au moins deux façons différentes.

  • Dans la famille ML des langues, un foncteur est un module qui prend un ou plusieurs autres modules comme paramètre. Il est considéré comme une fonctionnalité avancée, et la plupart des programmeurs commencent ont de la difficulté avec.

    À titre d'exemple de mise en œuvre et l'utilisation pratique, vous pouvez définir votre forme préférée d'arbre binaire équilibré une fois pour toutes comme foncteur, et il faudrait en paramètre un module qui fournit:

    • Le type de clé à utiliser dans l'arbre binaire

    • Une fonction totale ordre sur les touches

    Une fois que vous avez fait cela, vous pouvez utiliser la même mise en œuvre d'arbre binaire équilibré pour toujours. (Le type de valeur stockée dans l'arbre est généralement polymorphique l'arbre gauche ne faut pas regarder à des valeurs autres que de les copier autour, alors que l'arbre a vraiment besoin d'être en mesure de comparer les clés, et il obtient la fonction de comparaison de paramètre du foncteur.)

    Une autre application de ML functors est protocoles de réseau en couches . Le lien est un document vraiment formidable par le groupe Fox CMU; il montre comment utiliser foncteurs pour construire des couches de protocole plus complexes (comme TCP) sur le type de couches plus simples (comme IP ou même directement sur Ethernet). Chaque couche est implémenté comme un foncteur qui prend en tant que paramètre de la couche inférieure. La structure du logiciel reflète réellement la façon de penser au sujet du problème, par opposition aux couches existantes que dans l'esprit du programmeur. En 1994, lorsque ce travail a été publié, ce fut une grosse affaire.

    Pour un exemple sauvage de ML foncteurs en action, on pouvait voir le document Types Manifest, Modules et compilation séparée .

  • Dans Haskell, et dans un langage fonctionnel pur lié, Functor est classe de type . Un type appartient à une classe de type (ou plus techniquement, le type « est une instance de » la classe de type) lorsque le type fournit certaines opérations avec certains comportements attendus. Un type T peut appartenir à la classe Functor si elle a certains comportements comme la collection:

    • Le type T est paramétré sur un autre type, que vous devriez considérer comme le type d'élément de la collection. Le type de la collection complète est alors quelque chose comme T Int, T String, T Bool, si vous contenant des entiers, des chaînes ou des booléens respectivement. Si le type d'élément est inconnu, il est écrit comme paramètre de type a, comme dans T a.

      Les exemples incluent des listes (zéro ou plusieurs éléments de type a), le type de Maybe (zéro ou un élément de type a), ensembles d'éléments de type a, réseaux d'éléments de type a, toutes sortes d'arbres de recherche contenant des valeurs de type a, et beaucoup d'autres que vous pouvez penser.

    • L'autre propriété que T doit satisfaire est que si vous avez une fonction de type a -> b (fonction des éléments), alors vous devez être en mesure de prendre cette fonction et produit une fonction connexe sur les collections. Vous faites cela avec l'opérateurfmap, qui est partagé par tous les types de la classe de type Functor. L'opérateur est effectivement surchargé, donc si vous avez une even fonction de type Int -> Bool, puis

      fmap even
      

      est une fonction surchargée qui peut faire beaucoup de choses merveilleuses:

      • Convertir une liste d'entiers à une liste de booléens

      • Convertir un arbre d'entiers à un arbre de booléens

      • Convertir Nothing à Nothing et Just 7 à Just False

      Dans Haskell, cette propriété est exprimé en donnant le type de fmap:

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

      où nous avons maintenant un petit t, ce qui signifie "tout type dans la classe Functor."

    Pour faire une histoire courte, dans Haskell foncteur est une sorte de collection pour laquelle si vous donne une fonction sur les éléments, fmap vous redonner une fonction sur les collections . Comme vous pouvez l'imaginer, cela est une idée qui peut être largement réutilisé, ce qui explique pourquoi il est béni dans le cadre de la bibliothèque standard de Haskell.

Comme d'habitude, les gens continuent à inventer de nouvelles, des abstractions utiles, et vous pouvez regarder dans applicatif foncteurs, pour qui peut être un document appelé programmation Applicative avec des effets par Conor McBride et Ross Paterson.

Autres conseils

D'autres réponses ici sont complètes, mais je vais essayer une autre explication de l'utilisation de FP de foncteur . Prenez cela comme analogie:

  

A foncteur est un conteneur de type a qui, lorsqu'il est soumis à une fonction qui mappe de a b , donne un récipient de saisissez b .

Contrairement à l'utilisation fonction pointeur Abstraite en C ++, ici foncteur est pas la fonction; plutôt, il est quelque chose qui se comporte toujours quand soumis à une fonction .

Il y a trois significations différentes, et non! Beaucoup liés

  • OCaml est un module paramétré. Voir manuel. Je pense que la meilleure façon de assimilez est par exemple: (écrit rapidement, peut-être bogué)

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

Vous pouvez maintenant ajouter rapidement de nombreuses commandes possibles, les moyens de former de nouvelles commandes, faire une recherche binaire ou linéaire facilement sur eux. Programmation générique FTW.

  • Dans les langages de programmation fonctionnels comme Haskell, cela signifie que certains peuvent être « mis en correspondance » constructeurs de type (types paramétrés comme les listes, ensembles). Pour être précis, un foncteur f est équipé (a -> b) -> (f a -> f b). Cela a des origines dans la théorie des catégories. L'article de Wikipedia, est liée à cette utilisation.

    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
    

Alors, c'est un type particulier d'un constructeur de type, et a peu à voir avec foncteurs en Ocaml!

  • Dans les langues impératives, il est un pointeur de fonction.

En OCaml, il est un module paramétré.

Si vous connaissez C ++, pensez à un foncteur OCaml comme modèle. C ++ ne dispose que des modèles de classe et foncteurs travaillent à l'échelle du module.

Un exemple de foncteur est Map.Make; module StringMap = Map.Make (String);; construit un module de carte qui fonctionne avec des cartes de chaîne-clé.

Vous ne pouvez obtenir quelque chose comme StringMap avec le polymorphisme juste; vous avez besoin de faire quelques hypothèses sur les touches. Le module de chaîne contient les opérations (comparaison, etc.) sur un type de chaîne totalement ordonné, et le foncteur reliera contre les opérations du module de chaîne contient. Vous pourriez faire quelque chose de similaire avec la programmation orientée objet, mais vous auriez en tête de méthode indirection.

Vous avez un bon nombre de bonnes réponses. Je vais la hauteur dans:

A foncteur, au sens mathématique, est un type particulier de fonction sur une algèbre. Il est une fonction minimale qui associe une algèbre à une autre algèbre. « Minimalité » est exprimée par les lois des foncteurs.

Il y a deux façons de voir cela. Par exemple, les listes sont foncteurs sur un certain type. Ainsi, compte tenu d'une algèbre sur un type « a », vous pouvez générer une algèbre compatible des listes contenant des choses de type « a ». (Par exemple: la carte qui prend un élément à une liste singleton contenant: f (a) = [a]) Encore une fois, la notion de compatibilité est exprimée par les lois des foncteurs.

D'autre part, étant donné un foncteur f "plus" a un type, (qui est, fa est le résultat de l'application du foncteur f à l'algèbre de type a), et la fonction de g: a -> b, on peut calculer une nouvelle foncteur F = (fmap g) qui fait correspondre à f fa b. En bref, fmap est la partie de F qui fait correspondre les « parties » de foncteurs de « parties » de foncteurs, et g est la partie de la fonction qui fait correspondre les « parties d'algèbre » à « pièces » d'algèbre. Il faut une fonction, un foncteur, et une fois terminée, il est un foncteur aussi.

Il peut sembler que différentes langues utilisent différentes notions de foncteurs, mais ils ne sont pas. Ils sont simplement en utilisant foncteurs sur différentes algèbres. OCamls a une algèbre de modules et foncteurs plus que l'algèbre vous permettra de fixer de nouvelles déclarations à un module d'une manière « compatible ».

Un foncteur Haskell n'est pas une classe de type. Il est un type de données avec une variable libre qui satisfait à la classe de type. Si vous êtes prêt à creuser dans les entrailles d'un type de données (sans variables libres), vous pouvez réinterpréter un type de données en tant que foncteur sur une algèbre sous-jacente. Par exemple:

Données F = F Int

est isomorphe à la classe de Ints. Alors F, en tant que constructeur de valeur, est une fonction qui Int F Int, une algèbre équivalent. Il est un foncteur. D'autre part, vous ne recevez pas fmap gratuitement ici. C'est ce filtrage est pour.

Foncteurs sont bons pour « fixer » les choses à des éléments de algèbres, d'une manière compatible algébriquement.

Il y a un exemple assez bon dans le livre O'Reilly OCaml qui est sur le site de l'INRIA (qui, comme la rédaction de c'est malheureusement vers le bas). J'ai trouvé un exemple très similaire dans ce livre utilisé par Caltech: Introduction à OCaml ( lien pdf) . La section pertinente est le chapitre sur foncteurs (page 139 dans le livre, page 149 dans le PDF).

Dans le livre, ils ont un foncteur appelé MakeSet qui crée une structure de données qui se compose d'une liste, et les fonctions pour ajouter un élément, déterminer si un élément est dans la liste, et pour trouver l'élément. La fonction de comparaison qui est utilisée pour déterminer si elle est dans / pas dans le jeu a été paramétrées (qui est ce qui fait MakeSet un foncteur au lieu d'un module).

Ils ont également un module qui implémente la fonction de comparaison de manière à ne une affaire chaîne insensible comparer.

Utilisation du foncteur et le module qui implémente la comparaison, ils peuvent créer un nouveau module dans une ligne:

module SSet = MakeSet(StringCaseEqual);;

qui crée un module d'une structure de données de consigne qui utilise des comparaisons de casse. Si vous voulez créer un ensemble qui a utilisé des comparaisons sensibles cas alors vous juste besoin de mettre en œuvre un nouveau module de comparaison au lieu d'un nouveau module de structure de données.

Tobu par rapport aux modèles foncteurs en C ++ que je pense est tout à fait juste.

La meilleure réponse à cette question se trouve dans "Typeclassopedia" par Brent Yorgey.

Ce numéro de Monad lecteur contient une définition précise de ce qu'est un foncteur ainsi que beaucoup d'autres concepts définition ainsi qu'un diagramme. (Monoid, Applicative, le concept Monade et d'autres sont expliqués et vus par rapport à un foncteur).

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

extrait de Typeclassopedia pour Functor: « Une simple intuition est qu'un Functor représente un « conteneur » de certains sorte, ainsi que la possibilité d'appliquer une fonction uniformément à tous les éléments du conteneur "

Mais vraiment toute typeclassopedia est une lecture fortement recommandée qui est étonnamment facile. D'une certaine façon, vous pouvez voir la classe de types présenté il y a un parallèle à la conception modèle dans l'objet dans le sens où ils vous donnent un vocabulaire pour le comportement donné ou la capacité.

Vive

Voici un article sur foncteurs d'un POV de programmation , suivi de plus spécifiquement comment ils feront surface dans les langages de programmation .

L'utilisation pratique d'un foncteur est dans une monade, et vous pouvez trouver de nombreux tutoriels sur monades si vous regardez pour cela.

Compte tenu des autres réponses et ce que je vais poster maintenant, je dirais que c'est un mot assez lourdement surchargée, mais de toute façon ...

Pour une indication quant à la signification du mot « foncteur » dans Haskell, demandez 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

Donc, en gros, un foncteur dans Haskell est quelque chose qui peut être mis en correspondance sur. Une autre façon de le dire est qu'un foncteur est quelque chose qui peut être considéré comme un récipient qui peut être demandé d'utiliser une fonction donnée pour transformer la valeur qu'elle contient; Ainsi, pour les listes, fmap coïncide avec map, pour Maybe, fmap f (Just x) = Just (f x), fmap f Nothing = Nothing etc.

foncteur du paragraphe et de classe de types section foncteurs, et Monoïdes foncteurs Applicative de l'une des pages mentionnées ci-dessus .)

Dans un commentaire à haut-voté réponse , utilisateur Wei Hu demande:

  

Je comprends les ML-foncteurs et Haskell-foncteurs, mais manque le   un aperçu de les relier ensemble. Quelle est la relation entre ces   deux, dans un sens de la catégorie théorique?

Remarque :. Je ne sais pas ML, alors s'il vous plaît pardonner et corriger les erreurs liées

Supposons d'abord que nous sommes tous familiers avec les définitions de « catégorie » et « foncteur ».

Une réponse compacte serait que "Haskell-foncteurs" sont (endo) foncteurs F : Hask -> Hask alors que "ML-foncteurs" sont foncteurs G : ML -> ML'.

Ici, Hask est la catégorie formée par types Haskell et fonctions entre eux, et de même ML et ML' sont des catégories définies par des structures ML.

Remarque : Il y a quelques problèmes techniques avec Hask faire une catégorie, mais il existe des moyens autour d'eux.

Dans une catégorie perspective théorique, cela signifie qu'un Hask-foncteur est une F carte des types Haskell:

data F a = ...

avec une fmap carte des fonctions Haskell:

instance Functor F where
    fmap f = ...

ML est à peu près la même chose, mais il n'y a pas abstraction fmap canonique, je suis au courant, donc nous allons définir un:

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

C'est f Cartes ML-types et les fonctions fmap-maps de ML, donc

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

est un foncteur F: StructA -> StructB.

« Functor est la cartographie des objets et des morphisms qui conserve la composition et l'identité d'une catégorie. »

Permet de définir ce qui est une catégorie?

  

Il y a un tas d'objets!

     

Dessiner quelques points (pour l'instant 2 points, l'un est « a » est un autre « b ») à l'intérieur d'un   cercle et nom cercle A (Catégorie) pour l'instant.

Qu'est-ce que la catégorie détient?

  

Composition entre les objets et la fonction d'identité pour chaque objet.

Alors, nous devons cartographier les objets et préserver la composition après l'application de notre Functor.

laisse imaginer 'A' est notre catégorie qui a des objets [ 'a', 'b'] et il existe un morphisme a -> b

Maintenant, nous devons définir un foncteur qui permet de cartographier ces objets et morphismes dans une autre catégorie « B ».

Disons que le foncteur est appelé « Peut-être »

data Maybe a = Nothing | Just a

Ainsi, la catégorie « B » ressemble à ceci.

S'il vous plaît dessiner un autre cercle, mais cette fois avec « Peut-être un » et « Peut-être que b » au lieu de « a » et « b ».

Tout semble bon et tous les objets sont mis en correspondance

'a' est devenu 'Peut-être a' et 'b' est devenu 'Peut-être que b.

Mais le problème est que nous devons cartographier le morphisme de « a » à « b » ainsi.

Cela signifie morphisme a -> b dans 'A' devrait être calqué morphisme 'Peut-être un' -> 'Peut-être que b'

morphisme de a -> b est appelée f, puis morphisme de 'Peut-être un' -> 'Peut-être que b' est appelé 'fmap f'

Maintenant, voyons quelle fonction « f » a fait en « A » et voir si nous pouvons le reproduire dans « B »

définition de fonction

de 'f' en 'A':

f :: a -> b

f prend et renvoie b

définition d'une fonction de

'f' dans 'B':

f :: Maybe a -> Maybe b

f a peut-être un et le retour Peut-être que b

permet de voir comment utiliser fmap pour cartographier la fonction « f » de « A » de la fonction « fmap f » dans « B »

définition fmap

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

Alors, que faisons-nous ici?

Nous appliquons la fonction « f » à « x » qui est de type « a ». correspondance de motif spécial de « rien » vient de la définition de Functor Maybe.

Alors, nous avons cartographié nos objets [a, b] et morphismes [f] de la catégorie 'A' à la catégorie 'B'.

Cest Functor!

Pour ne pas contredire les précédentes réponses théoriques ou mathématiques, mais Functor est aussi un objet (dans un langage de programmation orienté objet) qui n'a qu'une seule méthode et est utilisé efficacement en fonction.

Un exemple est l'interface Runnable en Java, qui ne possède qu'une seule méthode:. Run

Considérons cet exemple, d'abord en Javascript, qui a des fonctions de première classe:

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

Sortie: [1, 4, 25, 100]

La méthode de la carte prend une fonction et retourne un nouveau tableau de chaque élément étant le résultat de l'application de cette fonction à la valeur à la même position dans la matrice d'origine.

Pour faire la même chose est de Java, en utilisant un Functor, vous devez d'abord définir une interface, disons que:

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

Alors, si vous ajoutez une classe de collection qui avait une fonction de carte, vous pouvez faire:

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

Celui-ci utilise une sous-classe de IntMapFunction en ligne afin de créer un Functor, ce qui est l'équivalent OO de la fonction de l'exemple JavaScript précédemment.

Utilisation Foncteurs vous permettent d'appliquer des techniques fonctionnelles dans un langage OO. Bien sûr, certaines langues OO ont également un soutien pour les fonctions directement, donc ce n'est pas nécessaire.

Référence: http://en.wikipedia.org/wiki/Function_object

Présentation brute

Dans la programmation fonctionnelle, un foncteur est essentiellement une construction de levage ordinaires unaire fonctions (à savoir ceux ayant un argument) des fonctions entre les variables des nouveaux types. Il est beaucoup plus facile d'écrire et de maintenir des fonctions simples entre les objets simples et foncteurs utiliser pour les soulever, puis d'écrire manuellement des fonctions entre les objets de conteneurs compliqués. Un autre avantage est d'écrire des fonctions simples qu'une seule fois, puis de les réutiliser par différents foncteurs.

Des exemples de foncteurs comprennent des tableaux, "peut-être" et "soit" foncteurs, à terme (voir par exemple https: // github.com/Avaq/Fluture ), et bien d'autres.

Illustration

On considère la fonction construire le nom de la personne complète des noms et prénoms. On pourrait le définir comme fullName(firstName, lastName) en fonction de deux arguments, mais ne serait pas approprié pour foncteurs qui traitent uniquement des fonctions d'un argument. Pour y remédier, nous recueillons tous les arguments dans un seul objet name, qui devient seul argument de la fonction:

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

Maintenant, si nous avons beaucoup de gens dans un tableau? Au lieu d'aller manuellement sur la liste, nous pouvons simplement réutiliser notre fonction fullName via la méthode map prévue des tableaux avec une seule ligne courte de code:

fullNameList = nameList => nameList.map(fullName)

et l'utiliser comme

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

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

Cela fonctionne, chaque fois que chaque entrée dans notre nameList est un objet fournissant à la fois des propriétés de firstName et lastName. Mais si certains objets ne pas (ou même ne sont pas des objets du tout)? Pour éviter les erreurs et rendre le code plus sûr, nous pouvons envelopper nos objets dans le type de Maybe (par exemple 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) est un conteneur portant uniquement les noms valides et Nothing() est la valeur spéciale utilisée pour tout le reste. Maintenant, au lieu d'interrompre (ou oublier) pour vérifier la validité de nos arguments, nous pouvons simplement réutiliser (ascenseur) notre fonction fullName originale avec une autre ligne de code, à nouveau basé sur la méthode de map, cette fois prévu pour le type Peut-être:

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

et l'utiliser comme

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

Catégorie Théorie

Functor Catégorie Théorie est une carte entre deux catégories relatives à la composition de leurs morphismes. Dans un Langage informatique , la principale catégorie d'intérêt est celui dont les objets sont types (certains ensembles de valeurs), et dont morphisms sont des fonctions f:a->b d'un type à un autre a b de type.

Par exemple, prendre a être le type de String, b le type de numéro, et f est la fonction mapper une chaîne dans sa longueur:

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

Ici a = String représente l'ensemble de toutes les chaînes et b = Number l'ensemble de tous les numéros. En ce sens, les deux a et b représentent des objets dans le Set Catégorie (qui est étroitement liée à la catégorie des types, la différence étant inessentiel ici). Dans la catégorie Set, morphismes entre deux ensembles sont précisément toutes les fonctions du premier jeu dans la seconde. Donc, notre fonction longueur f est ici un morphisme de l'ensemble des chaînes dans l'ensemble des nombres.

Comme nous considérons que la catégorie de jeu, le correspondant Foncteurs de celui-ci en lui-même sont des cartes d'envoi des objets à des objets et à morphismes morphismes, qui satisfont certaines lois algébriques.

Exemple: Array

Array peut signifier beaucoup de choses, mais une seule chose est une Functor - la construction de type, la cartographie d'un type a dans le [a] de type de tous les tableaux de type a. Par exemple, le foncteur Array cartes du type String dans le [String] de type (l'ensemble de tous les tableaux de chaînes de longueur arbitraire), et le type Number fixé dans le [Number] de type correspondant (l'ensemble de tous les tableaux de nombres).

Il est important de ne pas confondre la carte Functor

Array :: a => [a]

avec un a -> [a] morphisme. Le foncteur cartes simplement (associés) du type a dans le [a] de type comme une chose à l'autre. Que chaque type est en fait un ensemble d'éléments, est sans pertinence ici. En revanche, un morphisme est une fonction réelle entre ces ensembles. Par exemple, il existe un morphisme naturel (fonction)

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

qui envoie une valeur dans le tableau 1 éléments avec cette valeur comme seule entrée. Cette fonction est pas une partie du foncteur Array! Du point de vue de ce foncteur, pure est juste une fonction comme tout autre, rien de spécial.

D'autre part, le Array Functor a sa deuxième partie - la partie morphisme. Quelles cartes une f :: a -> b morphisme dans un [f] :: [a] -> [b] morphisme:

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

Ici arr est tout tableau de longueur arbitraire avec des valeurs de type a et arr.map(f) est le tableau de la même longueur avec des valeurs de type b, dont les entrées sont les résultats de l'application de f aux entrées de arr. Pour en faire un foncteur, les lois mathématiques de l'identité de la cartographie à l'identité et des compositions à des compositions doivent tenir, qui sont faciles à vérifier dans cet exemple de Array.

Baiser: Un foncteur est un objet qui a une méthode de carte

.

Les tableaux en JavaScript et mettre en œuvre la carte sont donc foncteurs. Les promesses, les ruisseaux et les arbres mettent souvent en œuvre la carte dans les langages fonctionnels, et quand ils le font, ils sont considérés comme foncteurs. La méthode de carte de foncteur prend propre contenu de elle et transforme chacun d'eux en utilisant la fonction de rappel de transformation passée à la carte, et retourne un nouveau foncteur, qui contient la structure comme la première foncteur, mais avec les valeurs transformées.

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

Dans la pratique, foncteur signifie un objet qui implémente l'opérateur d'appel en C ++. En OCaml Je pense que foncteur fait référence à quelque chose qui prend un module en entrée et la sortie d'un autre module.

Plus simplement, un foncteur, ou objet de fonction, est un objet de classe qui peut être appelée comme une fonction.

En C ++:

Voici comment vous écrivez une fonction

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

Voici comment vous écrivez un foncteur

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

Maintenant, vous pouvez faire ceci:

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

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

Ce qui rend ces si grand est que vous pouvez garder l'état dans la classe - imaginez si vous vouliez demander une fonction combien de fois il a été appelé. Il n'y a aucun moyen de le faire d'une manière nette, encapsulé. Avec un objet de fonction, il est comme toute autre classe. Vous auriez une variable d'instance que vous incrémenter dans operator () et une méthode pour inspecter cette variable, et tout est propre comme vous s'il vous plaît

Functor n'est pas lié spécifiquement à la programmation fonctionnelle. Il est juste un « pointeur » à une fonction ou une sorte d'objet, qui peut être appelé comme ce serait une fonction.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top