Memahami Functor, Applicative Functor, dan Monad dengan TypeScript
(evan-moon.github.io)Isi
- Menjelaskan dengan kode TypeScript proses yang berawal dari dua masalah yang tidak bisa diselesaikan hanya dengan
mappada functor (masalah fungsi yang terkurung di dalam container, dan masalah konteks yang bertumpuk saat komposisi) hingga sampai pada applicative functor dan monad - Dimulai dari latar belakang ketika Eugenio Moggi pada 1988 memodelkan program bukan sebagai
A → B, melainkanA → T(B) - Membahas struktur
flatMap = map + joindan tiga hukum untuk menggunakannya dengan aman (asosiatif, identitas kiri, identitas kanan) - Menjelaskan mengapa monad disebut "objek monoid dalam kategori endofunctor" dengan membandingkannya dengan monoid penjumlahan bilangan bulat
- Juga menyebutkan alasan
Promisebekerja secara monadik tetapi bukan monad matematis dalam arti yang ketat
Keterbatasan functor: hal-hal yang tidak bisa dilakukan dengan map
- Jika fungsi yang sudah di-curried diterapkan dengan
map, hasilnya membuat fungsi terkurung di dalam container sepertiMaybe<(b: number) => number>maphanya bisa menerima fungsi di luar container, sehingga tidak ada cara menerapkan fungsi yang terkurung di dalamnya ke nilai lain
- Jika dua fungsi yang mengembalikan functor dikomposisikan, konteks akan bertumpuk seperti
Maybe<Maybe>- Semakin banyak tahap, semakin bertumpuk tanpa batas menjadi
Maybe<Maybe<Maybe<...>>>
- Semakin banyak tahap, semakin bertumpuk tanpa batas menjadi
Applicative functor: menerapkan fungsi di dalam container
- Dengan operasi
apply, fungsi yang terkurung di dalam container bisa diterapkan ke nilai dari container lainapply: T<(A → B)> → T<A> → T<B>
- Dengan operasi
pure, nilai murni dimasukkan ke dalam container - Keterbatasannya: container mana saja yang akan dikomposisikan harus sudah ditentukan sebelumnya
- Tidak bisa mengekspresikan dependensi sekuensial dinamis yang menentukan komputasi berikutnya berdasarkan hasil komputasi sebelumnya
Monad: penemuan operasi untuk meratakan tumpukan
- Operasi
joinmeratakan container gandaT<T<A>> → T<A>menjadi satu lapisanArray.prototype.flatdi JavaScript menjalankan peran yang sama
- Dalam praktik, yang digunakan adalah
flatMap, gabunganmap + joinflatMap: T<A> → (A → T<B>) → T<B>mapmenerimaA → B, sedangkanflatMapmenerimaA → T<B>sehingga hasilnya tetap satu lapisan
Tiga hukum flatMap
- Hukum asosiatif: saat meratakan tiga lapisan
T(T(T(A))), hasilnya harus sama baik diratakan dari dalam dulu maupun dari luar dulum.flatMap(f).flatMap(g) === m.flatMap(x => f(x).flatMap(g))
- Hukum identitas kiri: jika nilai dimasukkan dengan
purelalu langsung di-flatMap, hasilnya sama seperti menerapkan fungsi secara langsungpure(a).flatMap(f) === f(a)
- Hukum identitas kanan: jika
purediberikan keflatMap, hasilnya tetap container semulam.flatMap(pure) === m
Mengurai "objek monoid dalam kategori endofunctor"
- Functor dalam pemrograman adalah endofunctor karena bergerak dari dunia tipe ke dunia tipe
- Kita bisa membentuk kategori endofunctor yang menjadikan endofunctor itu sendiri sebagai objek
- Jika dipetakan ke syarat monoid (operasi biner + hukum asosiatif + elemen identitas), hasilnya adalah:
- operasi biner =
join - elemen identitas =
pure - Strukturnya persis berkorespondensi dengan monoid penjumlahan bilangan bulat
- operasi biner =
Mengapa Promise bukan monad
thenmenangani campuranmapdanflatMaptergantung nilai kembalian- Keadaan
Promise<Promise>tidak diizinkan pada runtime dan langsung digabung menjadi satu lapisan - Praktis dan nyaman dalam kerja sehari-hari, tetapi tidak memenuhi hukum monad matematis
2 komentar
Tolong bahas juga Comonad!
Wah... saya akan memikirkannya dulu wkwkwk