# Functor: Từ Toán Học Đến Lập Trình Hàm
## 1. Mở đầu
Nếu bạn từng lập trình với `List.map` hay `Option.map` trong OCaml, bạn đã dùng **functor** mà có khi chưa nhận ra.
Nhưng functor không chỉ là một tiện ích lập trình: nó bắt nguồn từ **category theory** trong toán học — một lĩnh vực trừu tượng nghiên cứu “cấu trúc” và “liên kết giữa các cấu trúc”.
Bài viết này sẽ đi từ định nghĩa trong toán học, qua cách hiểu trong lập trình hàm, rồi minh họa bằng ví dụ thực tế.
```mermaid
flowchart LR
subgraph H2[Category Hask]
A2([int]) -- "f : int -> string" --> B2([string])
end
subgraph L[List functor]
AL([int list]) -- "List.map f : int list -> string list" --> BL([string list])
end
A2 -. "F maps objects" .-> AL
B2 -. "F maps objects" .-> BL
```
---
## 2. Category Theory và Functor
### Category là gì?
Một **category** bao gồm:
- **Objects** – thường nghĩ như các tập hợp hoặc kiểu dữ liệu.
- **Morphisms** – ánh xạ (hàm) giữa các đối tượng.
Kèm theo 2 quy tắc:
- **Identity**: mỗi đối tượng có một mũi tên đơn vị `id`.
- **Associativity**: hợp thành các morphism tuân thủ tính kết hợp.
Ví dụ:
- Category `Set`: objects là tập hợp, morphisms là hàm.
- Category `Int`: objects là kiểu số nguyên, morphisms là các hàm `int -> int`.
### Functor trong toán học
Một **functor** là ánh xạ giữa hai category `C` và `D` sao cho:
- Với mỗi object `A` trong `C`, có `F(A)` trong `D`
- Với mỗi morphism `f : A → B`, có `F(f) : F(A) → F(B)`
- Và phải thỏa:
- `F(id_A) = id_{F(A)}`
- `F(f ∘ g) = F(f) ∘ F(g)`
=> Functor bảo toàn cấu trúc của category.

---
## 3. Functor trong Lập Trình Hàm
Trong OCaml, một functor là một **type constructor** (kiểu tham số hóa) có thể "ánh xạ hàm" thông qua `map`.
`map : ('a -> 'b) -> 'a t -> 'b t`
Nó biến một hàm bình thường thành một hàm “trong bối cảnh”.
### Ví dụ: Option
```ocaml
let map_option f = function
| None -> None
| Some x -> Some (f x)
```
Kiểm tra luật functor:
```ocaml
let id x = x
map_option id (Some 7) = Some 7 (* identity *)
map_option (succ ∘ double) (Some 3) =
map_option succ (map_option double (Some 3)) (* composition *)
```
### Ví dụ: List
```ocaml
let map_list f lst = List.map f lst
```
```ocaml
map_list id [1;2;3] = [1;2;3] (* identity *)
map_list (succ ∘ double) [1;2;3] =
map_list succ (map_list double [1;2;3]) (* composition *)
```
---
## 4. Ý Nghĩa Thực Tế
Functor giúp xử lý dữ liệu "bên trong container" (option, list, result...) mà không phải viết lại logic lặp đi lặp lại.
Ví dụ:
```ocaml
map_option String.uppercase_ascii (Some "hello")
(* -> Some "HELLO" *)
List.map succ [1;2;3]
(* -> [2;3;4] *)
```
Dùng functor giúp code:
- Ngắn hơn
- Tổng quát hơn
- Dễ kết hợp (compose)
---
## 5. Từ Functor đến Các Khái Niệm Nâng Cao
Functor là nền tảng cho nhiều khái niệm khác trong lập trình hàm:
- **Applicative**: cho phép áp dụng hàm có nhiều tham số trong bối cảnh
- **Monad**: cho phép xâu chuỗi logic có phụ thuộc
- **Natural Transformation**: biến đổi tự nhiên giữa 2 functor
Ví dụ:
```ocaml
List.hd_opt : 'a list -> 'a option
```
là một natural transformation từ `list` sang `option`.
---
## 6. Kết luận
Functor là chiếc cầu nối giữa toán học trừu tượng và lập trình hiện đại.
- Trong **toán học**: functor là ánh xạ giữa các category, giữ nguyên cấu trúc.
- Trong **lập trình hàm**: functor là các kiểu có thể “ánh xạ hàm” như `option`, `list`, `result`.
Hiểu và sử dụng functor giúp bạn viết code rõ ràng, linh hoạt, và mở đường tiếp cận các khái niệm cao hơn như `applicative` và `monad`.
---