En Programmation Fonctionnelle, ce qui est un foncteur?

j'ai rencontré le terme "Functor" à quelques reprises en lisant divers articles sur la programmation fonctionnelle, mais les auteurs supposent généralement que le lecteur comprend déjà le terme. Regarder sur le web a fourni soit des descriptions excessivement techniques (voir article Wikipedia ) soit des descriptions incroyablement vagues (voir la section sur les foncteurs à ce OCaml-tutorial site ).

est-ce que quelqu'un peut être gentil définir le terme, expliquer son utilisation, et peut-être fournir un exemple de la façon dont les foncteurs sont créés et utilisés?

Edit : alors que je m'intéresse à la théorie derrière le terme, je suis moins intéressé par la théorie que je suis dans la mise en œuvre et l'utilisation pratique du concept.

Edit 2 : on dirait qu'il y a quelque cross-terminoligy en cours: je me réfère spécifiquement aux foncteurs de functional programmer, pas les objets de fonction de c++.

201
demandé sur Erik Forbes 2010-01-09 00:26:58

17 réponses

le mot" functor " vient de la théorie des catégories, qui est une branche très générale et très abstraite des mathématiques. Il a été emprunté par les concepteurs de langues fonctionnelles au moins de deux façons différentes.

  • dans la famille des langues ML, un functor 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 débutants ont des difficultés avec elle.

    comme exemple de mise en œuvre et d'utilisation pratique, vous pourriez définir votre forme préférée d'arbre de recherche binaire équilibré une fois pour toutes en tant que foncteur, et il prendrait comme paramètre un module qui fournit:

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

    • total-fonction de commande sur les touches

    une fois que vous avez fait cela, vous pouvez utilisez la même implémentation d'arbre binaire équilibrée pour toujours. (Le type de valeur stocké dans l'arbre est généralement polymorphique-l'arbre n'a pas besoin de regarder des valeurs autres que de les copier autour, alors que l'arbre a certainement besoin d'être en mesure de comparer des clés, et il obtient la fonction de comparaison à partir du paramètre du foncteur.)

    une autre application des foncteurs ML est protocole de réseau stratifié . Le lien est à un papier vraiment génial par le CMU Groupe Fox; il montre comment utiliser des foncteurs pour construire des couches de protocole plus complexes (comme TCP) sur des types de couches plus simples (comme IP ou même directement sur Ethernet). Chaque couche est implémentée comme un functor qui prend comme paramètre la couche au-dessous. La structure du logiciel reflète en fait la façon dont les gens pensent au problème, par opposition aux couches qui n'existent que dans l'esprit du programmeur. En 1994, quand ce travail a été publié, il a été une grande affaire.

    pour un exemple sauvage de functors ML en action, vous pouvez voir le papier ml Module Mania , qui contient un exemple publiable (c.-à-d., effrayant) de functors au travail. Pour une explication claire, brillante et pellucide du système de modules ML (avec des comparaisons avec d'autres types de modules), lisez les premières pages du brillant papier POPL 1994 de Xavier Leroy types manifestes, Modules, et Compilation séparée .

  • dans Haskell, et dans un langage purement fonctionnel apparenté, Functor est une classe de type . Un type appartient à une classe de type (ou plus techniquement, le type "est une instance de" la classe de type) quand le type fournit certaines opérations avec un certain comportement attendu. Un type T peut appartenir à la classe Functor s'il présente un certain comportement de 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 avez des entiers, des chaînes ou des booléens respectivement. Si le type d'élément est inconnue, il est écrit comme une paramètre de type a , comme dans T a .

      exemples: listes (zéro ou plusieurs éléments du type a ), le Maybe (zéro ou un des éléments de type a ), des ensembles d'éléments de type a , les tableaux d'éléments de type a , toutes sortes d'arbres de recherche contenant des valeurs de type a , et beaucoup d'autres personnes que vous pouvez penser.

    • l'autre propriété que T doit satisfaire est que si vous avez une fonction de type a -> b (une fonction sur les é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érateur fmap , qui est partagé par tous les types de la classe Functor type. L'opérateur est en fait surchargé, donc si vous avez une fonction even avec le type Int -> Bool , puis

      fmap even
      

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

      • convertissez une liste d'entiers en une liste de booléens

      • convertissez un arbre d'entiers en un arbre de booléens

      • convertir Nothing en Nothing et Just 7 en Just False

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

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

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

    pour faire court, dans Haskell un functor est une sorte de collection pour laquelle si on vous donne une fonction sur les éléments, fmap vous donnera une fonction sur les collections . Comme vous pouvez l'imaginer, c'est une idée qui peut être largement réutilisée, c'est pourquoi elle est bénie en tant que partie de la bibliothèque standard de Haskell.

comme d'habitude, les gens continuent à inventer de nouveaux, abstractions utiles, et vous voudrez peut-être regarder dans applicative functors, pour lequel la meilleure référence peut être un papier appelé Applicative Programming with Effects par Conor McBride et Ross Paterson.

254
répondu Norman Ramsey 2011-02-11 04:35:55

autres réponses ici sont complètes, mais je vais essayer une autre explication de L'utilisation de la FP functor . Prenez ceci comme analogie:

Un foncteur est un conteneur de type un qui, lorsqu'il est soumis à une fonction que des cartes à partir de un b , les rendements d'un conteneur de type b .

contrairement à la abstrait-la fonction de pointeur utiliser en C++, ici le foncteur est pas la fonction; c'est plutôt quelque chose qui se comporte de manière uniforme lors de la objet à une fonction .

54
répondu seh 2017-04-14 15:15:24

Il y a trois significations différentes, pas beaucoup!

  • en Ocaml c'est un module paramétrisé. Voir manuel . Je pense que la meilleure façon de grok, c'est par exemple: (écrit rapidement, peut-être buggé)

    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 beaucoup d'ordres possibles, des façons de former de nouveaux ordres, faire une recherche binaire ou linéaire facilement sur eux. Programmation générique FTW.

  • dans les langages de programmation fonctionnelle comme Haskell, cela signifie certains types de constructeurs (types paramétrés comme des listes, des ensembles) qui peuvent être "cartographiés". Pour être précis, un foncteur f est équipé de (a -> b) -> (f a -> f b) . Cela a des origines dans la catégorie de la théorie. L'article Wikipedia auquel vous avez fait référence est cet usage.

    class Functor f where
        fmap :: (a -> b) -> (f a -> f b)
    
    instance Functor [] where      -- lists are a functor
        fmap = map
    
    instance Functor Maybe where   -- Maybe is option in Haskell
        fmap f (Just x) = Just (f x)
        fmap f Nothing = Nothing
    
    fmap (+1) [2,3,4]   -- this is [3,4,5]
    fmap (+1) (Just 5)  -- this is Just 6
    fmap (+1) Nothing   -- this is Nothing
    

ainsi, il s'agit d'un type particulier d'un constructeur de type, et a peu à faire avec des foncteurs en Ocaml!

  • dans les langues impératives, c'est un pointeur pour fonctionner.
36
répondu sdcvvc 2010-12-18 13:38:08

en OCaml, c'est un module paramétré.

si vous connaissez C++, pensez à un foncteur OCaml comme un modèle. C++ n'a que des modèles de classe, et les foncteurs fonctionnent à l'échelle du module.

un exemple de functor est Map.Make; module StringMap = Map.Make (String);; construit un module de carte qui fonctionne avec des cartes à clé.

vous ne pouviez pas obtenir quelque chose comme StringMap avec juste du polymorphisme; vous devez faire quelques hypothèses sur les clés. chaîne module contient les opérations (comparaison, etc) sur un type de chaîne entièrement commandé, et le functor se liera avec les opérations que le module de chaîne contient. Vous pourriez faire quelque chose de similaire avec la programmation orientée objet, mais vous auriez méthode indirecte au-dessus.

15
répondu Tobu 2010-01-08 22:00:38

vous avez pas mal de bonnes réponses.

Un foncteur, dans le sens mathématique, est un type spécial de fonction sur une algèbre. Il s'agit d'une fonction minimale qui établit une correspondance entre une algèbre et une autre. La "minimalité" est exprimée par les lois de fonctionnement.

Il y a deux façons de regarder cette. Par exemple, les listes sont des foncteurs sur un certain type. C'est-à-dire, étant donné une algèbre sur un type 'a', vous pouvez générer une algèbre compatible de listes contenant des choses de type "a". (Par exemple: la carte qui prend un élément dans une liste unique le contenant: f (A) = [a]) encore une fois, la notion de compatibilité est exprimée par les lois de functor.

d'autre part, compte tenu d'un functeur f "sur" un type a, (c'est-à-dire, f A est le résultat de l'application du functeur f à l'algèbre de type a), et de la fonction de g: A - > b, Nous pouvons calculer un nouveau functeur F = (fmap g) qui correspond à f A à f B. En bref, fmap est la partie de f que les cartes "foncteur parties" à "foncteur pièces", et g est la partie de la fonction que les cartes de "l'algèbre des parties" à "l'algèbre de parties". Elle prend une fonction, un foncteur, et une fois terminé, il EST un foncteur.

il peut sembler que différentes langues utilisent des notions différentes de fonctions, mais elles ne le sont pas. Ils utilisent des foncteurs sur des algèbres différentes. OCamls a une algèbre de modules, et les foncteurs sur cette algèbre vous permettent d'attacher de nouvelles déclarations à un module dans un " compatible" façon.

Un Haskell foncteur n'est PAS un type de classe. C'est un type de données avec une variable libre qui satisfait la classe 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 comme un foncteur sur une algèbre sous-jacente. Par exemple:

données F = F Int

est isomorphe à la classe des Ints. Donc F, en tant que constructeur de valeurs, est une fonction qui établit une correspondance entre Int et F Int, un équivalent algèbre. C'est un foncteur. D'autre part, vous n'obtenez pas fmap gratuitement ici. C'est à ça que sert la correspondance des motifs.

Foncteurs sont bonnes pour la "fixation" des choses à des éléments de algèbres, dans un algébriquement compatible.

12
répondu user276631 2010-07-14 20:56:45

il y a un assez bon exemple dans le livre D'O'Reilly OCaml qui est sur le site Web de L'Inria (qui, au moment d'écrire ceci est malheureusement en baisse). 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 les foncteurs (page 139 dans le livre, page 149 dans le PDF).

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

ils ont également un module qui implante la fonction de comparaison de sorte qu'il fait une comparaison de chaîne de caractères insensible à la casse.

en utilisant le foncteur et le module qui met en œuvre la comparaison qu'ils peuvent créer un nouveau module en une ligne:

module SSet = MakeSet(StringCaseEqual);;

qui crée un module pour une structure de données établie qui utilise des comparaisons non sensibles à la casse. Si vous voulez créer un ensemble qui a utilisé des comparaisons sensibles à la casse, alors vous auriez juste besoin d'implémenter un nouveau module de comparaison au lieu d'un nouveau module de structure de données.

Tobu a comparé des foncteurs à des gabarits en C++ qui je pense est tout à fait approprié.

7
répondu Niki Yoshiuchi 2010-01-08 22:06:49

la meilleure réponse à cette question se trouve dans" Typeclassopedia " de Brent Yorgey.

ce numéro de Monad Reader contient une définition précise de ce qu'est un foncteur ainsi que de nombreuses définitions d'autres concepts ainsi qu'un diagramme. (Monoïde, Applicative, Monade et d'autres concepts sont expliqués et mis en relation avec un foncteur).

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

extrait de Typeclassopedia pour Functor: "Une simple intuition est qu'un Foncteur représente un "conteneur" de certains trier, avec la possibilité d'appliquer une fonction uniformément à chaque élément dans le conteneur "

mais vraiment toute la typeclassopedia est une lecture fortement recommandée qui est étonnamment facile. D'une certaine manière, vous pouvez voir la typeclass présentée ici comme un parallèle au modèle de conception dans l'objet dans le sens où ils vous donnent un vocabulaire pour un comportement donné ou capacité.

Cheers

7
répondu JFT 2010-01-09 23:36:09

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

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

5
répondu Craig Stuntz 2010-01-08 21:39:15

étant donné les autres réponses et ce que je vais poster maintenant, je dirais que c'est un mot plutôt surchargé, mais de toute façon...

pour un indice concernant le sens du mot "functor" 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, fondamentalement, un functor à Haskell est quelque chose qui peut être cartographié. Une autre façon de dire que c'est qu'un foncteur est quelque chose qui peut être considéré comme un conteneur qui peut être demandé d'utiliser une fonction pour transformer la valeur qu'il contient; ainsi, pour les listes, fmap coïncide avec map , Maybe , fmap f (Just x) = Just (f x) , fmap f Nothing = Nothing etc.

Le Foncteur typeclass sous-section et la section sur les Foncteurs, les Foncteurs Applicatifs et Monoids de Apprendre que Vous avez un Haskell pour le Grand Bien donner quelques exemples de cas où ce concept est utile. (Résumé: beaucoup d'endroits! :- ))

notez que n'importe quel monad peut être traité comme un functeur, et en fait, comme Craig Stuntz le fait remarquer, les functeurs les plus souvent utilisés ont tendance à être des monades... OTOH, il est parfois commode de faire d'un type une instance du Functor typeclass sans se donner la peine d'en faire un Monad. (P. ex. dans le cas de ZipList de Control.Applicative , mentionné sur l'une des pages susmentionnées .)

5
répondu Michał Marczyk 2010-01-08 22:18:32

dans un commentaire au haut-voté réponse , l'utilisateur Wei Hu demande:

je comprends à la fois ML-functors et Haskell-functors, mais manque le perspicacité pour les relier ensemble. Quelle est la relation entre ces deux, dans une catégorie de la théorie des sens?

Note : Je ne sais pas ML, alors s'il vous plaît pardonner et corriger toutes les erreurs connexes.

supposons d'abord que nous connaissons tous les définitions de "catégorie" et de "fonction".

une réponse compacte serait que" Haskell-functors "sont (endo-)functors F : Hask -> Hask tandis que" ML-functors "sont functors G : ML -> ML' .

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

Note : il y a quelques problèmes techniques avec faire Hask une catégorie, mais il y a des moyens de les contourner.

d'un point de vue théorique de catégorie, cela signifie qu'un Hask -functor est une carte F des types Haskell:

data F a = ...

accompagné d'une carte fmap des fonctions de Haskell:

instance Functor F where
    fmap f = ...

ML, c'est joli. de la même façon, bien qu'il n'y ait pas d'abstraction canonique fmap dont je suis conscient, alors définissons-en une:

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

C'est-à-dire f cartes ML - types et fmap cartes ML - fonctions, so

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

est un foncteur F: StructA -> StructB .

5
répondu Ncat 2017-05-23 11:54:59

"Foncteur est mappage d'objets et de morphisms qui préserve la composition et de l'identité d'une catégorie."

permet de définir ce qu'est une catégorie ?

C'est un tas d'objets!

dessinez quelques points (pour l'instant 2 points, un est 'a' un autre est 'b') à l'intérieur d'un Encerclez et nommez ce cercle A (catégorie) pour l'instant.

que contient cette catégorie ?

Composition entre objets et fonction D'identité pour chaque objet.

ainsi, nous devons cartographier les objets et préserver la composition après avoir appliqué notre foncteur.

imaginons que 'A' soit notre catégorie qui a des objets ['a', 'b'] et qu'il existe un morphisme a - > b

maintenant, nous devons définir un functor qui peut mapper ces objets et morphismes dans une autre catégorie 'B'.

disons le functor est appelé 'peut-être'

data Maybe a = Nothing | Just a

Ainsi, La catégorie " B " ressemble à ceci.

dessinez un autre cercle, mais cette fois avec "peut-être a" et "peut-être b" au lieu de " a " et "b".

Tout semble bon et tous les objets sont mappés

' a 'est devenu' peut-être a 'et' b 'est devenu'peut-être b'.

mais le problème est que nous devons aussi cartographier le morphisme de " a " à "b".

qui signifie morphisme a - > b EN 'A' devrait correspondre au morphisme' peut-être a '- > 'peut-être b'

morphisme de a - > b s'appelle f, puis morphisme de 'peut-être a' - > 'peut-être b' s'appelle' fmap f '

permet maintenant de voir quelle fonction' f 'faisait dans 'A' et voir si nous pouvons la répliquer dans ' b '

définition de la fonction de 'f' dans 'Un':

f :: a -> b

F prend A et retourne b

Fonction

définition de " f "dans " B":

f :: Maybe a -> Maybe b

F prend peut-être a et retourne peut-être b

permet de voir comment utiliser fmap pour mapper la fonction 'f' de 'A' de la fonction 'fmap f' dans le 'B'

définition de fmap

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

alors, qu'est-ce qu'on fait ici ?

nous appliquons la fonction 'f' à 'x' qui est de type 'a'. L'appariement spécial de "rien" vient de la définition de Functor Maybe .

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

C'Est Foncteur!

enter image description here

3
répondu Sumanth Kumar Mora 2017-03-16 13:36:24

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

un exemple est L'interface exécutable en Java, qui n'a qu'une seule méthode: exécuter.

considérons cet exemple, d'abord dans 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 map prend une fonction et renvoie un nouveau tableau avec chaque élément étant le résultat de l'application de cette fonction à la valeur à la même position dans le tableau d'origine.

pour faire la même chose est Java, en utilisant un Functor, vous auriez d'abord besoin de définir une interface, dire:

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

alors, si vous ajoutez une classe collection qui a une fonction de carte, vous pouvez faire:

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

Ceci utilise une sous-classe en ligne de IntMapFunction pour créer un Functor, qui est l'équivalent OO de la fonction de L'exemple JavaScript précédent.

L'utilisation de Functors vous permet d'appliquer des techniques fonctionnelles dans un langage OO. Bien sûr, certains langages OO ont aussi un support direct pour les fonctions, donc ce n'est pas nécessaire.

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

2
répondu Kevin Greer 2014-11-29 21:15:12

Aperçu

dans la programmation fonctionnelle, un functor est essentiellement une construction de levage ordinaires unary fonctions (c.-à-d. ceux avec un argument) à des fonctions entre les variables de nouveaux types. Il est beaucoup plus facile d'écrire et de maintenir des fonctions simples entre des objets simples et d'utiliser des foncteurs pour les soulever, puis d'écrire manuellement des fonctions entre des objets containers compliqués. Outre l'avantage d' écrire des fonctions simples une seule fois et les réutiliser par l'intermédiaire de différents foncteurs.

exemples de fonctions: tableaux, fonctions" peut-être "et" l'un ou l'autre", futures (voir par exemple https://github.com/Avaq/Fluture ), et bien d'autres.

Illustration

considérez la fonction construisant le nom complet de la personne à partir du prénom et du nom de famille. Nous pourrions le définir comme fullName(firstName, lastName) en fonction de deux arguments, qui ne seraient toutefois pas appropriés pour les foncteurs qui traitent uniquement des fonctions d'un argument. Pour y remédier, nous collectons tous les arguments dans un seul objet name , qui devient maintenant l'argument unique de la fonction:

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

que se passe-t-il si nous avons beaucoup de monde en bataille? Au lieu d'aller manuellement sur la liste, nous pouvons simplement réutiliser notre fonction fullName via la méthode map prévue pour les 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']

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

Théorie Des Catégories

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

par exemple, prendre a pour être le String type, b le type de nombre, et f est la fonction mapping une chaîne dans sa longueur:

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

ici a = String représente l'ensemble de toutes les cordes et b = Number l'ensemble de tous les nombres. En ce sens, a et b représentent tous deux des objets catégorie (qui est étroitement liée à la catégorie des types, la différence étant essentielle ici). Dans la catégorie des ensembles, morphismes entre deux ensembles sont précisément toutes les fonctions du premier ensemble au second. Ainsi notre fonction de longueur f voici un morphisme de l'ensemble des cordes dans l'ensemble des nombres.

comme nous ne considérons que la catégorie des ensembles, les Functors " pertinents 1519630920" de lui dans lui-même sont des cartes envoyant des objets aux objets et des morphismes aux morphismes, qui satisfont certaines lois algébriques.

exemple: Array

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

il est important de ne pas confondre le foncteur carte

Array :: a => [a]

avec un morphisme a -> [a] . Le foncteur mappe simplement le type a dans le type [a] comme une chose à une 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 est naturel morphism (fonction)

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

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

d'autre part, le Array Functor a sa deuxième partie -- la partie morphisme. Qui trace une carte du morphisme f :: a -> b en un morphisme [f] :: [a] -> [b] :

// 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 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 la cartographie l'identité à l'identité et les compositions aux compositions doivent tenir, qui sont faciles à vérifier dans cet exemple Array .

2
répondu Dmitri Zaitsev 2016-12-29 03:40:06

KISS: un functor est un objet qui a une méthode de carte.

Les tableaux

en JavaScript implémentent la carte et sont donc des foncteurs. Les promesses, les ruisseaux et les arbres mettent souvent en œuvre la carte dans des langues fonctionnelles, et quand ils le font, ils sont considérés comme des foncteurs. La méthode map du functor prend ses propres contenus et transforme chacun d'eux en utilisant le callback de transformation passé à map, et renvoie un nouveau functor, qui contient la structure comme premier functor, mais avec le valeurs transformées.

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

1
répondu soundyogi 2016-03-07 22:05:54

en pratique, functor signifie un objet qui implémente l'opérateur d'appel en C++. En ocaml je pense functor se réfère à quelque chose qui prend un module comme entrée et sortie un autre module.

-3
répondu feng 2014-09-09 22:22:27

plus simplement, un functor, ou objet de fonction, est un objet de classe qui peut être appelé comme une fonction.

En C++:

C'est comme ça qu'on écrit une fonction

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

c'est comme ça qu'on écrit un functor

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 grands 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 ordonnée, encapsulée. Avec un objet de fonction, c'est comme n'importe quelle autre classe: vous avez une variable d'instance que vous incrémentez dans operator () et une méthode pour inspecter cette variable, et tout est propre comme vous voulez.

-5
répondu Matt 2010-01-08 21:47:09

Foncteur n'est pas spécifiquement liées à la programmation fonctionnelle. C'est juste un "pointeur" vers une fonction ou un type d'objet, qui peut être appelé, comme il le serait une fonction.

-9
répondu alemjerus 2010-01-08 21:31:24