Dijelaskan dalam 5 menit: Monads dalam JavaScript biasa
Terlepas dari foto sampul yang mengintimidasi, saya akan mencoba menjelaskan monad menggunakan matematika sesedikit mungkin. Tidak disebutkan teori kategori, tidak ada Kleisli, bahkan Curry pun tidak. Meskipun akan ada NaN.
Dalam kata-kata Douglas Crockford yang agung:
Selain bagus dan berguna, itu juga dikutuk dan kutukan monad adalah begitu Anda mendapatkan pencerahan, begitu Anda mengerti - "oh begitulah" - Anda kehilangan kemampuan untuk menjelaskannya kepada orang lain.
Yah, saya punya teori - ini karena di antara semua artikel bagus tentang hal ini, yang memberikan penjelasan bagus tentang teori matematika di balik monad, dan bagaimana mereka harus diterapkan (bersama dengan contoh-contoh indah!), satu hal yang salah:
Untuk apa saya sebenarnya membutuhkannya?
Sebelum kita mencoba mencari tahu, satu komentar. Beberapa waktu yang lalu, saya membaca bahwa Anda seharusnya tidak mencoba memahami monad berdasarkan apa pun yang tidak didasarkan pada penjelasan matematika di baliknya dan tempatnya dalam Teori Kategori. Bagi mereka yang tertarik: ada beberapa artikel bagus yang membahas subjek itu, seperti ini , atau yang ini , atau yang memperkenalkan monad ke dalam pemrograman dari tahun 1992 . Karena saya benar-benar tidak ingin mengulanginya di sini, harap baca (atau setidaknya pindai) sekarang dan kembali ke sini sesudahnya (walaupun saya percaya bahwa tidak sepenuhnya perlu untuk memahami apa yang terjadi selanjutnya).
Oke, sekarang kita sudah menyingkir - apa itu monad? Nah, cara paling sederhana untuk mengatakannya adalah — ini adalah pembungkus dari beberapa nilai. Dalam hal pemrograman fungsional, monad adalah functor , struktur yang memungkinkan penerapan fungsi padanya. Ini adalah lapisan ekstra abstraksi antara nilai dan pemrosesan apa pun yang ingin kita berikan nilai. Tapi itu tidak memberi tahu kita apa-apa.
Mari kita lihat monad paling sederhana yang dapat Anda bayangkan: implementasi Identitymonad:
const Identity = (value) => ({
value: () => value,
map: (fn) => Identity(fn(value)),
});
Mari kita lihat contoh paling sederhana:
const addTax = (value) => value * 1.1;
const cartValue = Identity(100);
const cartValueWithTax = cartValue
.map(addTax) // At this point this is Identity(110)
.value(); // Equal to 110 as a number
IdentityMonad memiliki — seperti identityfungsi di banyak pustaka pemrograman fungsional — logika yang cukup transparan. Ini adalah monad placeholder, sama seperti identityfungsi placeholder. Menerapkan addTaxnilai kita bekerja dengan baik untuk skenario yang diberikan di atas, tetapi mari pikirkan tentang apa yang akan terjadi jika nilai keranjang kita sama dengan undefined. Berkat cara kerja JavaScript yang luar biasa , kita akan mendapatkan file NaN.
Biasanya, untuk menyiasatinya, cara yang paling intuitif adalah menambahkan tanda centang untuk nilai ke addTaxfungsi. Ini adalah pendekatan yang salah. Itu mengaburkan tujuan fungsi dan membuatnya kurang murni. Fungsi addTaxharus melakukan hanya satu hal dan hanya satu hal add: Tax.
Oke, orang bijak - Anda mungkin berkata - bagaimana kita harus memperhitungkan undefinednilainya? Nah, untuk itulah kami memiliki monad. Kami ingin menjaga fungsi tetap murni. Kami juga ingin logika kami berperilaku berbeda berdasarkan nilai yang kami berikan ke fungsi. Tempat terbaik untuk mendefinisikan perilaku itu adalah functor !
Mari kita lihat monad yang mungkin paling populer: Maybe. Ini mungkin implementasi dasar (saya meninggalkan metode biasa yang mungkin Anda temui di monad seperti ofuntuk kejelasan):
const Maybe = (value) => ({
value: () => value,
map: (fn) => value === undefined || value === null
? Maybe(null)
: Maybe(fn(value)),
});
const primitiveCart = 100;
const undefinedCart = undefined;
const nullishCart = null;
const maybeCart = Maybe(100);
const maybeUndefinedCart = Maybe(undefined);
const maybeNullishCart = Maybe(null);
addTax(primitiveCart); // boring, 110
addTax(undefinedCart); // NaN
addTax(nullishCart); // 0 - thanks, JavaScript!
maybeCart.map(addTax).value(); // 110
maybeUndefinedCart.map(addTax).value(); // null
maybeNullishCart.map(addTax).value(); // null
Ini, tentu saja, hanya goresan dari banyaknya kemungkinan yang dibawa oleh penggunaan monad. Katakanlah kita ingin menyapa setiap tamu yang masuk ke hotel kita:
const greet = (name) => `Hello, ${name}!`;
Mari kita lihat satu contoh dasar lagi — Optionalmonad:
const Optional = (value) => ({
value: () => value,
orElse: (alternativeValue) => value
? Optional(value)
: Optional(alternativeValue),
map: (fn) => Optional(fn(value)),
});
const firstGuest = "John";
const anonymousGuest = undefined;
greet(firstGuest); // "Hello, John!"
greet(anonymousGuest); // "Hello, undefined" - this is a bit embarrasing
const OptionalWithStrangerFallback = (name) => Optional(name)
.orElse("stranger");
const firstGuestOptional = OptionalWithStrangerFallback(firstGuest);
const anonymousGuestOptional = OptionalWithStrangerFallback(anonymousGuest);
// I really hope you know where this is going at this point
firstGuestOptional.map(greet).value(); "Hello, John!"
anonymousGuestOptional.map(greet).value(); "Hello, stranger!"
Saya sangat berharap ini menyelesaikan masalah dengan monad. Jika tidak, beri tahu saya di komentar! Juga, jika Anda ingin membaca lebih banyak artikel tentang JavaScript, pemrograman fungsional, visi komputer, arsitektur, geometri, meme, kepemimpinan teknis, atau campuran apa pun di atas, pastikan untuk mengikuti saya di sini atau di LinkedIn !

![Apa itu Linked List? [Bagian 1]](https://post.nghiatu.com/assets/images/m/max/724/1*Xokk6XOjWyIGCBujkJsCzQ.jpeg)



































