Functional Programming: Mengenal Kleisli

Kleisli itu cuma function composition buat Monad

Jihad Dzikri Waspada
codewey
3 min readJul 4, 2017

--

Dulu, ketika pertama kali mendengar istilah Kleisli, yang ada dalam pikiran saya adalah mantan saya yang unyu ini:

Ini Khaleesi woy!

Eh tapi ternyata dia lebih memilih pria lain dan malah jadi bintang film. Da saya mah apa atuh, cuma setitik upil kering di padang pasir…

*Krik krik* Balik ke topik. Bagi kamu-kamu yang dalemin functional programming, pasti tau dong apa itu function composition.

Terus juga pasti tau dong apa itu Monad.

Nah kan udah tau nih. Sekarang saya mau ngenalin istilah baru, Kleisli. Ga usah banyak babibu, langsung aja ke kodingan.

Monad Function Composition

Kayak yang sebelum-sebelumnya, saya berikan contoh data yang familiar saja:

const person = {
name: 'Munir',
age: 59,
child: {
name: 'Jihad',
age: 24
}
}

lalu ada soal pelajaran Kimia yang berbunyi: Berapakah nilai umur anak orang dibagi 2? Yang kita harap jawabannya adalah 12. Untuk menjawab soal tersebut, kita buat dulu fungsi-fungsi dasarnya:

Pertanyaan kimia SNMPTN

Dan, dengan menggunakan Monad, kita bisa membuat solusinya dengan method bind

const res = Maybe(data)
.bind(getChild)
.bind(getAge)
.bind(safeDivisionBy(2))
console.log(res)
// => Maybe(12)

Pertanyaannya

Bagaimana kalau kita mau buat sebuah function getHalfOfChildsAge karena (misalkan) akan digunakan di banyak tempat? Akankah seperti ini?

const getHalfOfChildsAge = compose(
safeDivisionBy(2),
getAge,
getChild
)
console.log(getHalfOfChildsAge(person)) // atau
console.log(getHalfOfChildsAge(Maybe.of(person)))
// TETOOT, keduanya tak bisa

Analisa

Mari kita lihat fungsi getHalfOfChildsAge dari type signature-nya dulu.

Nah dari situ aja udah keliatan bentrok. Fungsi getAge expect Person tapi malah dapet Maybe Person dan begitu juga safeDivisionBy yang expect Number tapi malah dapet Maybe Number. Gak match. Terus gimana solusinya?

Introduce The Mother of Dragon, The Kleisli!

Kita mulai dari naming dulu ya, karena tau sendiri, “Naming things is hard in Computer Science”. Nah, karena Kleisli ini fungsinya mirip-mirip dengan compose, kita sepakati saja kita akan buat sebuah fungsi bernama composeK, alias compose Kleisli. Yang nantinya bisa dipake kayak gini.

const getHalfOfChildsAge = composeK(
safeDivisionBy(2),
getAge,
getChild
)
console.log(getHalfOfChildsAge(person))
// => Just(12)

Implementasinya gimana pakde?

Sama seperti compose, kita gunakan reduceRight, tapi dengan pemanggilan bind di setiap iterasinya.

Simple banget pakde

Ya memang begitu.

Bingung pakde

Gini-gini. Kita pake kasus yang di atas aja ya. Mulai dari pertanyaan pertama. Kenapa ada const lastArg = fns.pop? Jawabannya karena saya ndak tau implementasi Monad yang mau dipake; bisa Maybe, Either, IO, atau yang lainnya. Makanya lastArg itu isinya adalah getChild dan lastArg(init) isinya getChild(person). Sampai step ini, kita jadi tahu bahwa nilai yang di-pass ke dalam fungsi reduce akan bernotasi Maybe Person, dan juga kita jadi tahu ketika melakukan acc.bind(x), variable acc ini merupakan instance dari Maybe, yang pada akhirnya fungsi fns.reduceRight akan mengembalikan Maybe juga.

Kita jadi tahu (source)

Pertanyaan kedua: kenapa pake bind di dalam fungsi reduce-nya? Coba kita recall lagi problem dengan compose tadi. Fungsi getAge expect Person, sedangkan dapetnya malah Maybe Person dari fungsi getChild. Jadi, harus ada suatu mekanisme (fungsi) yang bisa “membuka” Maybe Person menjadi Person. Fungsi apakah itu? Tadaa, fungsi bind pada Monad! Ingat kan notasi seperti ini?

M[A].bind(fn: A => M[B]): M[B]

in our case,

Maybe[Person].bind(fn: Person => Maybe[Number]): Maybe[Number]

Nah disini jadi terlihat kan fungsi bind adalah pihak yang bertugas membuka bungkus Maybe[Person] menjadi Person (saya buat bold lho itu). Lalu jika diperhatikan lebih dalam lagi, kita bisa lihat notasi fn di atas, Person => Maybe[Number] atau yang juga bisa dituliskan sebagai Person → Maybe Number, merupakan type signature yang dimiliki oleh fungsi getAge. Cucok!

Gampang kan ya? 😙

Kesimpulan

Sahabat-sahabatku yang super,

Kleisli adalah salah satu cara melakukan function composition untuk fungsi-fungsi yang mengembalikan nilai ber-instance Monad

Itu. 👴🏼👉🏼

Penutup

Semoga temen-temen (including me) tetep terus semangat belajar konsep-konsep dari Functional Programming. Jangan terlalu pusing terbawa sama jargon-jargonnya; Monad, Functor, Monoid, Semigroup, Endofunctor, Applicative, Kleisli, Compose, Currying, Lift, Morphism, Type Signature, Algebraic Data Type, bla bla bla bla. Doakan supaya kita diperbanyak sama tutorial-tutorial bagus berbahasa Indonesia. Tolongin Baim Ya Allah.. Amin.

For further discussion, please don’t hesitate to comment below! 💚

--

--

Jihad Dzikri Waspada
codewey

Software Developer @Chordify, Utrecht. NOTE: Please navigate to https://jihadwaspada.com. I no longer write on Medium