Functori
Programatorii sunt obișnuiți cu conceptul de functor și pot recunoaște tipuri generice, cum sunt listele, ca functori în limbajele orientate pe obiecte, deoarece de obicei au o metodă map/fmap/select care pot transforma o listă de tip List<int> într-o listă List<string> printr-o funcție .
Adevărul este că conceptul de functor din matematică și cel din programare reprezintă același concept din perspective diferite. Corespondența nu este întotdeauna intuitivă și evidentă, iar în continuare vom arăta de ce.
Definiție: Functor
Un functor de la o categorie la alta , notat , este o mapare care trimite într-un obiect și care trimite într-un morfism , astfel încât:
- conservă compoziția:
- conservă identitatea:
Practic, un functor este un homomorfism (mapare care conservă structura) între două categorii.
Posibila formalizare in Lean 4
class Functor (C : Category ObjC) (D: Category ObjD) where
mapObj : ObjC -> ObjD
mapHom : ∀ {x y : ObjC}, C.Hom x y -> D.Hom (mapObj x) (mapObj y)
conserveComp : ∀ {x y z : ObjC} (g : C.Hom y z) (f : C.Hom x y), D.comp (mapHom g) (mapHom f) = mapHom (C.comp g f)
conserveId : ∀ {x : ObjC}, mapHom (C.id x) = D.id (mapObj x)
Legătura cu programarea
Revenind la corespondența între programare și matematică, putem evidenția legătura considerând următorul exemplu. Să presupunem că, în cadrul unui program, avem trei tipuri de date: int, bool și string, cu următoarele funcții între ele: și . Să presupunem că tipurile noastre de bază reprezintă o categorie, cu tipurile fiind obiecte, iar funcțiile morfisme. Dacă am introduce un functor numit ca un tip generic care are o funcție , atunci tuplul reprezintă functorul conform definiției date, ca cele două mapări pe obiecte, respectiv morfisme.
Acesta este doar un exemplu care să ilustreze conceptual ideea de functor pentru un programator. În realitate, formalizarea sistemelor de tipuri sub forma de categorii este mult mai complexă.
Ce putem observa aici este că functorul nu conservă structura internă a unui tip de date - aceasta este irelevantă într-un context funcțional - ci conservă structura relațiilor între tipurile de date. De asemenea, pentru alte tipuri generice cu diferite proprietăți, trebuie incluse mai multe obiecte și morfisme în categoria destinație pentru functor. Categoria destinație poate include alte obiecte și morfisme la care nu se mapează din categoria sursă.
Compunere
La fel ca morfismele și functorii pot fi compuși, dacă avem functorii și atunci va exista un functor care aplicat pe și duc în respectiv .
Functorul identitate
Un caz special de (endo)functor este functorul identitate (endofunctorii sunt functori cu sursa și destinația aceiași categorie) care satisface proprietățile:
Astfel acest functor pentru conpunerea oricare functori , satisface relațiile:
Functori covarianți și contravarianți
În general, dacă avem un funtor de tipul îl vom numi covariant iar atunci când functorul are ca domeniul de definiție categoria opusă îl numim contravariant. Aceste două noțiuni se văd cel mai clar prin functorul definit pentru o categorie local mică . Acest functor este definit duce o pereche de obiecte în mulțimea a tuturor morfismelor de la la .
Dacă fixam un atunci obținem doi functori, care este covariant și contravariant. Functorul este covariant pentru că dacă avem un morfism atunci avem unde . Functorul este contravariant pentru că un morfism atunci există unde .