functional-programming-jargon/readme.md
2017-06-15 16:50:44 +07:00

1064 lines
27 KiB
Markdown

# Jargon Pemrograman Fungsional
_Functional programming_ (FP) atau pemrograman fungsional memberikan banyak
keuntungan, dan kini popularitasnya telah meningkat sebagai hasilnya. Namun,
setiap paradigma pemrograman datang dengan jargon uniknya masing-masing
dan FP tidak terkecuali. Dengan memberikan glosarium,
kami berharap dapat mempermudah belajar FP.
Contoh yang ada disajikan dalam JavaScript (ES2015).
[Kenapa JavaScript?](https://github.com/hemanth/functional-programming-jargon/wiki/Why-JavaScript%3F)
*Ini adalah sebuah
[WIP](https://github.com/hemanth/functional-programming-jargon/issues/20)
dari
[Functional Programming Jargon](https://github.com/hemanth/functional-programming-jargon/)
milik [hemanth](https://github.com/hemanth/); Jangan ragu untuk mengirim PR ;)*
Jika ada, dokumen ini menggunakan istilah yang didefinisikan dalam spesifikasi
[Fantasy Land](https://github.com/fantasyland/fantasy-land).
__Daftar Isi__
<!-- RM(noparent,notop) -->
* [Arity](#arity)
* [Higher-Order Functions (HOF)](#higher-order-functions-hof)
* [Partial Application](#partial-application)
* [Currying](#currying)
* [Closure](#closure)
* [Auto Currying](#auto-currying)
* [Function Composition](#function-composition)
* [Continuation](#continuation)
* [Purity](#purity)
* [Side Effect](#side-effects)
* [Idempotent](#idempotent)
* [Point-Free Style](#point-free-style)
* [Predicate](#predicate)
* [Contract](#contract)
* [Category](#category)
* [Value](#value)
* [Constant](#constant)
* [Functor](#functor)
* [Pointed Functor](#pointed-functor)
* [Lift](#lift)
* [Referential Transparency](#referential-transparency)
* [Equational Reasoning](#equational-reasoning)
* [Lambda](#lambda)
* [Lambda Calculus](#lambda-calculus)
* [Lazy evaluation](#lazy-evaluation)
* [Monoid](#monoid)
* [Monad](#monad)
* [Comonad](#comonad)
* [Applicative Functor](#applicative-functor)
* [Morphism](#morphism)
* [Endomorphism](#endomorphism)
* [Isomorphism](#isomorphism)
* [Setoid](#setoid)
* [Semigroup](#semigroup)
* [Foldable](#foldable)
* [Type Signature](#type-signature)
* [Algebraic data type](#algebraic-data-type)
* [Sum type](#sum-type)
* [Product type](#product-type)
* [Option](#option)
* [Pustaka Pemrograman Fungsional dalam JavaScript](#pustaka-pemrograman-fungsional-dalam-javascript)
<!-- /RM -->
## Arity
_Arity_ merupakan banyaknya argumen yang diambil oleh fungsi.
Berasal dari kata-kata seperti _unary_, _binary_, _ternary_, dan lain-lain.
Kata ini memiliki perbedaan yang terdiri dari dua sufiks, "-ary" dan "-ity."
Penjumlahan, misalnya, mengambil dua argumen, dan jadi didefinisikan sebagai
fungsi biner (_binary function_) atau fungsi dengan dua _arity_.
Fungsi semacam itu terkadang disebut "_dyadic_" oleh orang-orang yang lebih
menyukai bahasa Yunani dari bahasa Latin.
Demikian juga, fungsi yang mengambil sejumlah variabel argumen disebut
"_variadic_", sedangkan fungsi biner harus diberikan dua dan hanya dua
argumen, meskipun _currying_ dan _partial application_ (lihat di bawah).
```js
const sum = (a, b) => a + b
const arity = sum.length
console.log(arity) // 2
// Arity dari fungsi `sum` adalah dua
```
## Higher-Order Functions (HOF)
_Higher-Order Function_ adalah sebuah fungsi yang mengambil fungsi sebagai
argumen dan/atau mengembalikan sebuah fungsi.
```js
const filter = (predicate, xs) => xs.filter(predicate)
```
```js
const is = (type) => (x) => Object(x) instanceof type
```
```js
filter(is(Number), [0, '1', 2, null]) // [0, 2]
```
## Partial Application
Menerapkan fungsi secara parsial (_Partial Application_ atau Fungsi Parsial)
artinya membuat fungsi baru dengan mengisi beberapa argumen ke fungsi semula.
```js
// Helper membuat sebagian fungsi yang diaplikasikan
// Mengambil sebuah fungsi dan beberapa argumen
const partial = (f, ...args) =>
// mengembalikan sebuah fungsi yang mengambil sisa argumen
(...moreArgs) =>
// dan memanggil fungsi asilnya dengan semuanya
f(...args, ...moreArgs)
// Sesuatu untuk diaplikasikan
const add3 = (a, b, c) => a + b + c
// Menerapkan `2` dan `3` secara parsial ke `add3`
// Sehingga, memberikan Anda sebuah fungsi dengan satu argumen
const fivePlus = partial(add3, 2, 3) // (c) => 2 + 3 + c
fivePlus(4) // 9
```
Anda juga dapat menggunakan `Function.prototype.bind` untuk menerapkan
fungsi parsial di JavaScript:
```js
const add1More = add3.bind(null, 2, 3) // (c) => 2 + 3 + c
```
_Partial application_ atau fungsi parsial membantu menciptakan fungsi yang
lebih sederhana dari yang lebih kompleks dengan memadukan data saat Anda
memilikinya. [_Curried_](#currying) _function_ sudah secara otomatis diterapkan
secara parsial.
## Currying
_Currying_ merupakan sebuah proses mengubah fungsi yang membutuhkan banyak
argumen menjadi fungsi yang membawa mereka satu-persatu.
Setiap kali fungsi dipanggil hanya menerima satu argumen dan mengembalikan
sebuah fungsi yang membutuhkan satu argumen sampai semua argumen dilewatkan.
```js
const sum = (a, b) => a + b
const curriedSum = (a) => (b) => a + b
curriedSum(40)(2) // 42.
const add2 = curriedSum(2) // (b) => 2 + b
add2(10) // 12
```
## Closure
_Closure_ merupakan sebuah cara untuk mengakses sebuah variabel yang berada
di luar cakupannya.
Secara formal, _closure_ merupakan sebuah teknik untuk menerapkan _lexically
scoped_ bernama _binding_. Ini adalah cara untuk menyimpan sebuah fungsi
dengan sebuah _environment_.
_Closure_ adalah lingkup yang menangkap variabel lokal dari suatu fungsi untuk
askes bahkan setelah eksekusi telah berpindah dari blok yang didefinisikan.
Yaitu, mereka membiarkan referensi lingkup setelah blok dimana variabel
dinyatakan telah selesai mengeksekusi.
```js
const addTo = x => y => x + y
var addToFive = addTo(5)
addToFive(3) // mengembalikan 8
```
Fungsi `addTo()` mengembalikan sebuah fungsi (secara internal disebut `add()`),
lalu disimpan di variabel yang disebut `addToFive` dengan _curried call_ yang
memiliki parameter `5`.
Idealnya, ketika fungsi `addTo` selesai dieksekusi, cakupannya,
dengan variabel lokal `add`, `x`, `y` seharusnya tidak dapat diakses. Tapi,
itu mengembalikan `8` ketika memanggil `addToFive()`. Ini artinya kondisi
dari fungsi `addTo` disimpan bahkan setelah blok kode selesai dieksekusi.
Jika tidak, tidak mungkin dapat mengetahui bahwa `addTo` telah dipanggil
sebagai `addTo(5)` dan nilai dari `x` telah ditentukan menjadi `5`.
_Lexical scoping_ adalah alasan mengapa ia dapat menemukan nilai dari `x` dan
`add` - sebuah variabel _private_ induk yang telah selesai dieksekusi.
Nilai ini disebut _Closure_.
`Stack` beserta `lexical scope` fungsinya disimpan dalam bentuk referensi
ke induknya. Hal ini mencegah _closure_ dan variabel-variabel mendasar agar
tidak dikumpulkan sebagai sampah (karena setidaknya ada satu refernsi
langsung untuk itu).
__Lambda Vs. Closure__
_Lambda_ pada dasarnya adalah fungsi yang didefinisikan secara _inline_
daripada metode standar untuk mendeklarasikan fungsi. Lambda sering dapat
dilewatkan sebagai objek.
_Closure_ adalah fungsi yang membungkus keadaan sekitarnya dengan
mereferensikan bidang yang ada di luar tubuhnya. _State_ tertutup tetap
berada di seberang seruan _closure_.
__Bacaan lebih lanjut/Sumber__
* [Lambda Vs Closure](http://stackoverflow.com/questions/220658/what-is-the-difference-between-a-closure-and-a-lambda)
* [How do JavaScript Closures Work?](http://stackoverflow.com/questions/111102/how-do-javascript-closures-work)
## Auto Currying
_Auto currying_ mengubah fungsi yang membutuhkan banyak argumen menjadi
argumen yang jika diberikan kurang dari jumlah argumen yang benar mengembalikan
sebuah fungsi yang mengambil sisanya. Bila fungsi mendapatkan jumlah argumen
yang benar, maka akan dievaluasi.
lodash dan Ramda memiliki fungsi `curry` yang bekerja seperti di bawah.
```js
const add = (x, y) => x + y
const curriedAdd = _.curry(add)
curriedAdd(1, 2) // 3
curriedAdd(1) // (y) => 1 + y
curriedAdd(1)(2) // 3
```
__Bacaan lebih lanjut__
* [Favoring Curry](http://fr.umio.us/favoring-curry/)
* [Hey Underscore, You're Doing It Wrong!](https://www.youtube.com/watch?v=m3svKOdZijA)
## Function Composition
_Function composition_ atau komposisi fungsi adalah tindakan yang menempatkan
dua fungsi bersama untuk membentuk fungsi ketiga dimana keluaran dari satu
fungsi adalah masukan dari yang lain.
```js
const compose = (f, g) => (a) => f(g(a)) // Definisi
const floorAndToString = compose((val) => val.toString(), Math.floor) // Penggunaan
floorAndToString(121.212121) // '121'
```
## Continuation
Pada suatu titik dalam sebuah program, bagian dari kode yang belum dieksekusi
dikenal sebagai kelanjutan/kontinuitas atau _continuation_.
```js
const printAsString = (num) => console.log(`Given ${num}`)
const addOneAndContinue = (num, cc) => {
const result = num + 1
cc(result)
}
addOneAndContinue(2, printAsString) // 'Given 3'
```
Kontinuitas sering terlihat pada pemrograman _asynchronous_ saat program
perlu menunggu untuk menerima data sebelum dapat melanjutkan. Responnya
sering dilewatkan ke sisa program, yang merupakan kelanjutannya, begitu
sudah diterima.
```js
const continueProgramWith = (data) => {
// Melanjutkan program dengan data
}
readFileAsync('path/to/file', (err, response) => {
if (err) {
// mengatasi galat
return
}
continueProgramWith(response)
})
```
## Purity
Sebuah fungsi dikatan murni atau _pure_ jika mengembalikan nilai yang hanya
ditentukan oleh nilai masukannya, dan tidak menghasilkan efek samping
atau _side effect_.
```js
const greet = (name) => `Hi, ${name}`
greet('Brianne') // 'Hi, Brianne'
```
Berbeda dengan masing-masing hal di bawah:
```js
window.name = 'Brianne'
const greet = () => `Hi, ${window.name}`
greet() // "Hi, Brianne"
```
Contoh keluaran di atas didasarkan pada data yang tersimpan di luar fungsi...
```js
let greeting
const greet = (name) => {
greeting = `Hi, ${name}`
}
greet('Brianne')
greeting // "Hi, Brianne"
```
... dan yang satu ini memodifikasi keadaan di luar fungsi.
## Side Effect
Sebuah fungsi atau ekspresi dikatakan memiliki efek samping jika selain
mengembalikan nilai, ia berinterasksi dengan (membaca dari atau menulis ke)
keadaan yang dapat berubah eksternal.
```js
const differentEveryTime = new Date()
```
```js
console.log('IO is a side effect!')
```
## Idempotent
Suatu fungsi _idempotent_ jika mengaplikasikannya kembali hasilnya tidak
menghasilkan hasil yang berbeda.
```
f(f(x)) ≍ f(x)
```
```js
Math.abs(Math.abs(10))
```
```js
sort(sort(sort([2, 1])))
```
## Point-Free Style
Menulis fungsi dimana definisi tidak secara eksplisit mengidentifikasi
argumen yang digunakan. Gaya ini biasanya memerlukan [_currying_](#currying)
atau lainnya [_Higher-Order function_](#higher-order-functions-hof).
Alias, _Tacit programming_.
```js
// Diberikan
const map = (fn) => (list) => list.map(fn)
const add = (a) => (b) => a + b
// Lalu
// Bukan points-free - `numbers` merupakan argumen eksplisit
const incrementAll = (numbers) => map(add(1))(numbers)
// Points-free - `list` merupakan argumen implisit
const incrementAll2 = map(add(1))
```
`incrementAll` mengidentifikasi dan menggunakan parameter `numbers`, jadi itu
bukan _points-free_. `incrementAll2` dituliskan hanya dengan menggabungkan
beberapa fungsi dan beberapa nilai, membuatnya tidak menyebut satu pun
argumennya. Itu __adalah__ _points-free_.
Definisi _points-free function_ terlihat seperti _assignment_ normal tanpa
`function` atau `=>`.
## Predicate
Suatu _predicate_ adalah sebuah fungsi yang mengembalikan nilai `true` atau
`false` untuk suatu nilai yang diberikan. Biasanya digunakan sebagai _callback_
untuk menyaring _array_.
```js
const predicate = (a) => a > 2
;[1, 2, 3, 4].filter(predicate) // [3, 4]
```
## Contract
Suatu _contract_ menentukan kewajiban dan jaminan perilaku dari suatu fungsi
atau ekspresi saat _runtime_. Ini bertindak sebagai seperangkat aturan yang
diharapkan dari masukan dan keluaran suatu fungsi atau ekspresi, dan
kesalahan umumnya dilaporkan setiap kali sebuah kontrak dilanggar.
```js
// Mendefinisikan contract kami : int -> int
const contract = (input) => {
if (typeof input === 'number') return true
throw new Error('Contract violated: expected int -> int')
}
const addOne = (num) => contract(num) && num + 1
addOne(2) // 3
addOne('some string') // Contract violated: expected int -> int
```
## Category
Kategori dalam _category theory_ adalah kumpulan objek dan morfisme
(_morphism_) di antara keduanya. Dalam pemrograman, biasanya _types_ bertindak
sebagai objek dan fungsi sebagai morfisme.
Untuk menjadi kategori yang sah, tiga aturan harus dipenuhi:
1. Harus ada morfisme identitas yang memetakan objek itu sendiri.
Dimana `a` adalah sebuah objek dalam beberapa kategori,
harus ada fungsi dari `a -> a`.
2. Morfisme harus disusun.
Dimana `a`, `b`, dan `c` adalah objek dalam beberapa kategori,
dan `f` adalah morfisme dari `a -> b`, serta `g` adalah morfisme dari
`b -> c`; `g(f(x))` harus sama dengan `(g • f)(x)`.
3. Komposisi harus asosiatif.
`f • (g • h)` sama halnya dengan `(f • g) • h`.
Karena aturan ini mengatur komposisi pada tingkat yang sangat abstrak,
teori kategori sangat bagus dalam menemukan cara baru untuk menyusun sesuatu.
__Bacaan lebih lanjut__
* [Category Theory for Programmers](https://bartoszmilewski.com/2014/10/28/category-theory-for-programmers-the-preface/)
## Value
Apa saja yang dapat di-_assign_ ke variabel.
```js
5
Object.freeze({name: 'John', age: 30}) // The `freeze` function enforces immutability.
;(a) => a
;[1]
undefined
```
## Constant
Sebuah variabel yang tidak dapat ditetapkan kembali setelah ditentukan nilainya.
```js
const five = 5
const john = Object.freeze({name: 'John', age: 30})
```
_Constant_ atau konstanta adalah
[_referentially transparent_](#referential-transparency). Artinya, mereka
dapat diganti dengan nilai yang mereka wakili tanpa mempengaruhi hasilnya.
Dengan dua konstanta di atas, ekspresi berikut akan selalu mengembalikan
nilai `true`.
```js
john.age + five === ({name: 'John', age: 30}).age + (5)
```
## Functor
Suatu objek yang mengimplementasikan fungsi `map`, yang ketika menjalankan
lebih dari setiap nilai pada objek untuk menghasilkan objek baru, mematuhi
dua aturan:
__Preserves identity__
```
object.map(x => x) ≍ object
```
__Composable__
```
object.map(compose(f, g)) ≍ object.map(g).map(f)
```
(`f`, `g` menjadi fungsi sewenang-wenang)
_Functor_ umum dalam JavaScript adalah `Array` karena mematuhi dua aturan
_functor_, yaitu:
```js
[1, 2, 3].map(x => x) // = [1, 2, 3]
```
dan
```js
const f = x => x + 1
const g = x => x * 2
;[1, 2, 3].map(x => f(g(x))) // = [3, 5, 7]
;[1, 2, 3].map(g).map(f) // = [3, 5, 7]
```
## Pointed Functor
Suatu objek dengan sebuah fungsi `of` yang mengambil _semua_ nilai tunggal
ke dalamnya.
ES2015 menambahkan `Array.of` yang menjadikannya _pointed functor_.
```js
Array.of(1) // [1]
```
## Lift
_Lifting_ atau mengangkat (dari kata _lift_, angkat) adalah saat Anda
mengambil sebuah nilai dan mengambilnya ke dalam suatu objek seperti
[functor](#pointed-functor). Jika Anda mengangkat sebuah fungsi ke dalam
[Applicative Functor](#applicative-functor), maka Anda dapat membuatnya
bekerja pada nilai-nilai yang juga ada di _functor_ itu.
Beberapa implementasi memiliki fungsi yang disebut `lift`, atau `liftA2` agar
lebih mudah menjalankan fungsi pada _functor_.
```js
const liftA2 = (f) => (a, b) => a.map(f).ap(b) // catatan: itu `ap`, bukan `map`.
const mult = a => b => a * b
const liftedMult = liftA2(mult) // fungsi ini sekarang bekerja pada functor seperti array
liftedMult([1, 2], [3]) // [3, 6]
liftA2(a => b => a + b)([1, 2], [3, 4]) // [4, 5, 5, 6]
```
Mengangkat fungsi satu argumen dan menerapkannya melakukan hal yang sama
seperti `map`.
```js
const increment = (x) => x + 1
lift(increment)([2]) // [3]
;[2].map(increment) // [3]
```
## Referential Transparency
Sebuah ekspresi yang dapat diganti nilainya dengan tanpa mengubah tingkah laku
program tersebut dikatan _referentially_ transparan.
Katakanlah kita memiliki fungsi `greet`:
```js
const greet = () => 'Hello World!'
```
Setiap seruan dari `greet()` dapat ditimpa dengan `Hello World!`, karena itu
`greet` secara referensial transparan.
## Equational Reasoning
Ketika sebuah aplikasi terdiri dari ekspresi dan tanpa efek samping,
kebenaran tentang sistem dapat diturunkan dari bagian-bagiannya.
## Lambda
Fungsi anonim yang dapat diperlakukan seperti sebuah nilai.
```js
;(function (a) {
return a + 1
})
;(a) => a + 1
```
_Lambda_ juga sering dilewatkan sebagai argumen ke _Higher-Order function_.
```js
[1, 2].map((a) => a + 1) // [2, 3]
```
Anda dapat menugaskan (_assign_) suatu _lambda_ ke dalam sebuah variabel.
```js
const add1 = (a) => a + 1
```
## Lambda Calculus
Sebuah cabang dari matematika yang menggunakan fungsi untuk membuat suatu
[model universal dari komputasi](https://en.wikipedia.org/wiki/Lambda_calculus).
## Lazy evaluation
_Lazy evaluation_ adalah mekanisme evaluasi panggilan-per-kebutuhan yang
menunda evaluasi suatu ekspresi sampai nilainya dibutuhkan. Dalam bahasa
fungsional, ini memungkinkan struktur seperti _infinite list_, yang biasanya
tidak tersedia dalam bahasa imperatif dimana urutan perintah sangat penting.
```js
const rand = function*() {
while (1 < 2) {
yield Math.random()
}
}
```
```js
const randIter = rand()
randIter.next() // Setiap eksekusi memberikan nilai acak, ekspresi dievaluasi hanya saat dibutuhkan
```
## Monoid
Objek dengan fungsi yang "menggabungkan" objek itu sendiri dengan tipe lain
yang sama.
Salah satu _monoid_ sederhana adalah penjumlahan angka:
```js
1 + 1 // 2
```
Dalam kasus ini, angka adalah objek dan `+` adalah fungsi.
Nilai "identitas" juga harus ada bila dikombinasikan dengan nilai yang tidak
mengubahnya.
Nilai identitas untuk penjumlahan adalah `0`.
```js
1 + 0 // 1
```
Ini juga memerlukan pengelompokkan operasi yang tidak akan mempengaruhi
hasilnya (asosiatif):
```js
1 + (2 + 3) === (1 + 2) + 3 // true
```
Rangkaian _array_ juga membentuk _monoid_:
```js
;[1, 2].concat([3, 4]) // [1, 2, 3, 4]
```
Nilai identitasnya adalah _array_ kosong atau `[]`.
```js
;[1, 2].concat([]) // [1, 2]
```
Jika fungsi identitas dan komposisi disediakan, maka fungsinya membentuk monoid:
```js
const identity = (a) => a
const compose = (f, g) => (x) => f(g(x))
```
`foo` adalah fungsi apapun yang mengambil satu argumen.
```
compose(foo, identity) ≍ compose(identity, foo) ≍ foo
```
## Monad
_Monad_ adalah sebuah objek dengan fungsi [`of`](#pointed-functor) dan `chain`.
`chain` ini seperti [`map`](#functor), kecuali itu "membatalkan" objek
bersarang yang dihasilkan.
```js
// Implementasi
Array.prototype.chain = function (f) {
return this.reduce((acc, it) => acc.concat(f(it)), [])
}
// Penggunaan
;Array.of('cat,dog', 'fish,bird').chain((a) => a.split(',')) // ['cat', 'dog', 'fish', 'bird']
// Kontras ke map
;Array.of('cat,dog', 'fish,bird').map((a) => a.split(',')) // [['cat', 'dog'], ['fish', 'bird']]
```
`of` juga diketahui sebagai `return` di bahasa fungsional lainnya.
`chain` juga diketahui sebagai `flatmap` dan `bind` di bahasa lainnya.
## Comonad
Suatu objek yang memiliki fungsi `extract` dan `extend`.
```js
const CoIdentity = (v) => ({
val: v,
extract () {
return this.val
},
extend (f) {
return CoIdentity(f(this))
}
})
```
`extract` mengambil sebuah nilai keluar dari _functor_.
```js
CoIdentity(1).extract() // 1
```
_extend_ menjalankan fungsi di atas _comonad_. Fungsi tersebut seharusnya
mengembalikan tipe yang sama dengan _comonad_.
```js
CoIdentity(1).extend((co) => co.extract() + 1) // CoIdentity(2)
```
## Applicative Functor
Suatu _applicative functor_ adalah sebuah objek dengan fungsi `ap`. `ap`
menerapkan fungsi pada objek ke nilai objek lain dari tipe yang sama.
```js
// Implementasi
Array.prototype.ap = function (xs) {
return this.reduce((acc, f) => acc.concat(xs.map(f)), [])
}
// Contoh penggunaan
;[(a) => a + 1].ap([1]) // [2]
```
Ini berguna jika Anda memiliki dua objek dan Anda ingin menerapkan fungsi biner
ke isinya.
```js
// Array yang ingin digabungkan
const arg1 = [1, 3]
const arg2 = [4, 5]
// menggabungkan fungsi - harus curried untuk pekerjaan ini
const add = (x) => (y) => x + y
const partiallyAppliedAdds = [add].ap(arg1) // [(y) => 1 + y, (y) => 3 + y]
```
Ini memberi Anda sebuah _array_ dari sejumlah fungsi yang dapat Anda sebut `ap`
untuk mendapatkan hasilnya:
```js
partiallyAppliedAdds.ap(arg2) // [5, 6, 7, 8]
```
## Morphism
Sebuah fungsi transformasi.
### Endomorphism
Sebuah fungsi dimana tipe masukannya sama dengan keluarannya.
```js
// uppercase :: String -> String
const uppercase = (str) => str.toUpperCase()
// decrement :: Number -> Number
const decrement = (x) => x - 1
```
### Isomorphism
Sepasang transformasi antara dua jenis benda yang bersifat struktural dan tidak
ada data yang hilang.
Sebagai contoh, koordinat 2D dapat disimpan sebagai _array_ `[2, 3]` atau objek
`{x: 2, y: 3}`.
```js
// Menyediakan fungsi untuk mengubah kedua arah membuat mereka isomorfik
const pairToCoords = (pair) => ({x: pair[0], y: pair[1]})
const coordsToPair = (coords) => [coords.x, coords.y]
coordsToPair(pairToCoords([1, 2])) // [1, 2]
pairToCoords(coordsToPair({x: 1, y: 2})) // {x: 1, y: 2}
```
## Setoid
Suatu objek yang memiliki fungsi `equals` yang mana dapat digunakan untuk
membandingkan objek lain dengan tipe yang sama.
Menjadikan _array_ suatu _setoid_:
```js
Array.prototype.equals = function (arr) {
const len = this.length
if (len !== arr.length) {
return false
}
for (let i = 0; i < len; i++) {
if (this[i] !== arr[i]) {
return false
}
}
return true
}
;[1, 2].equals([1, 2]) // true
;[1, 2].equals([0]) // false
```
## Semigroup
Suatu objek yang memiliki fungsi `concat` yang menggabungkannya dengan objek
lain dengan tipe yang sama.
```js
;[1].concat([2]) // [1, 2]
```
## Foldable
Suatu objek yang memiliki fungsi `reduce` yang dapat mengubah objek tersebut
menjadi tipe yang lain.
```js
const sum = (list) => list.reduce((acc, val) => acc + val, 0)
sum([1, 2, 3]) // 6
```
## Type Signature
Seringkali fungsi dalam JavaScript memiliki komentar yang menunjukkan tipe dari
argumen dan nilai pengembaliannya.
Ada sedikit perbedaan di antara komunitas/masyarakat, namun mereka sering
mengikuti pola berikut:
```js
// functionName :: firstArgType -> secondArgType -> returnType
// add :: Number -> Number -> Number
const add = (x) => (y) => x + y
// increment :: Number -> Number
const increment = (x) => x + 1
```
Jika suatu fungsi menerima fungsi lain sebagai argumennya, maka itu dibungkus
dengan tanda kurung.
```js
// call :: (a -> b) -> a -> b
const call = (f) => (x) => f(x)
```
Huruf `a`, `b`, `c`, `d` digunakan sebagai tanda bahwa argumen tersebut dapat
berbentuk apa saja. Layaknya versi dari `map`, mengambil sebuah fungsi
yang mengubah nilai dari bentuk `a` ke bentuk lain `b`, sebuah _array_ dengan
nilai berbentuk `a`, dan mengembalikan sebuah _array_ dengan nilai berbentuk
`b`.
```js
// map :: (a -> b) -> [a] -> [b]
const map = (f) => (list) => list.map(f)
```
__Bacan lebih lanjut__
* [Ramda's type signatures](https://github.com/ramda/ramda/wiki/Type-Signatures)
* [Mostly Adequate Guide](https://drboolean.gitbooks.io/mostly-adequate-guide/content/ch7.html#whats-your-type)
* [What is Hindley-Milner?](http://stackoverflow.com/a/399392/22425) di Stack Overflow
## Algebraic data type
Jenis komposit yang dibuat dari jenis lainnya. Dua kelas umum dari tipe aljabar
(_algebraic type_) adalah [_sum_](#sum-type) dan [_product_](#product-type).
### Sum type
_Sum type_ adalah kombinasi dari dua _type_ menjadi satu sama lain. Ini disebut
jumlah (_sum_) karena jumlah nilai yang mungkin terjadi pada _type_ hasil
adalah jumlah dari tipe masukan.
JavaScript tidak memiliki _type_ seperti ini, tapi kita dapat menggunakan `Set`
untuk berpura-pura:
```js
// bayangkan bahwa daripada Set di sini kita memiliki tipe yang hanya memiliki nilai-nilai ini
const bools = new Set([true, false])
const halfTrue = new Set(['half-true'])
// Tipe `weakLogic` mengandung jumlah nilai dari `bools` dan `halfTrue`
const weakLogicValues = new Set([...bools, ...halfTrue])
```
_Sum type_ terkadang disebut _union type_, _discriminated union_, atau _tagged
union_.
Ada [beberapa](https://github.com/paldepind/union-type)
[pustaka](https://github.com/puffnfresh/daggy) dalam JavaScript yang
membantu mendefinisikan dan menggunakan _union type_.
_Flow_ memasukkan [_union type_](https://flow.org/en/docs/types/unions/) dan
TypeScript memiliki
[Enums](https://www.typescriptlang.org/docs/handbook/enums.html) untuk melayani
peran yang sama.
### Product type
Tipe ***product*** menggabungkan beberapa tipe bersama, dengan cara yang mungkin
Anda telah akrab:
```js
// point :: (Number, Number) -> {x: Number, y: Number}
const point = (x, y) => ({x: x, y: y})
```
Ini disebut produk (_product_) karena nilai total dari struktur data adalah
produk dari nilai yang berbeda. Banyak bahasa memiliki tipe _tuple_ yang
merupakan formulasi sederhana dari _product type_.
Lihat juga [teori himpunan](https://id.wikipedia.org/wiki/Teori_himpunan).
## Option
_Option_ adalah suatu _[sum type](#sum-type)_ dengan dua kasus yang sering
disebut `Some` dan `None`.
_Option_ sangat berguna untuk menyusun fungsi-fungsi yang mungkin tidak
mengembalikan sebuah nilai.
```js
// Definisi naif
const Some = (v) => ({
val: v,
map (f) {
return Some(f(this.val))
},
chain (f) {
return f(this.val)
}
})
const None = () => ({
map (f) {
return this
},
chain (f) {
return this
}
})
// maybeProp :: (String, {a}) -> Option a
const maybeProp = (key, obj) => typeof obj[key] === 'undefined' ? None() : Some(obj[key])
```
Gunakan `chain` untuk mengurutkan fungsi yang mengembalikan `Option`.
```js
// getItem :: Cart -> Option CartItem
const getItem = (cart) => maybeProp('item', cart)
// getPrice :: Item -> Option Number
const getPrice = (item) => maybeProp('price', item)
// getNestedPrice :: cart -> Option a
const getNestedPrice = (cart) => getItem(obj).chain(getPrice)
getNestedPrice({}) // None()
getNestedPrice({item: {foo: 1}}) // None()
getNestedPrice({item: {price: 9.99}}) // Some(9.99)
```
`Option` juga dikenal sebagai `Maybe`. `Some` terkadang disebut `Just`.
`None` terkadang disebut `Nothing`.
## Pustaka Pemrograman Fungsional dalam JavaScript
* [mori](https://github.com/swannodette/mori)
* [Immutable](https://github.com/facebook/immutable-js/)
* [Ramda](https://github.com/ramda/ramda)
* [ramda-adjunct](https://github.com/char0n/ramda-adjunct)
* [Folktale](http://folktalejs.org)
* [monet.js](https://cwmyers.github.io/monet.js/)
* [lodash](https://github.com/lodash/lodash)
* [Underscore.js](https://github.com/jashkenas/underscore)
* [Lazy.js](https://github.com/dtao/lazy.js)
* [maryamyriameliamurphies.js](https://github.com/sjsyrek/maryamyriameliamurphies.js)
* [Haskell in ES6](https://github.com/casualjavascript/haskell-in-es6)
---
__P.S:__ _Repository_ ini di-_fork_ dari proyek
[_Functional Programming Jargon_](https://github.com/hemanth/functional-programming-jargon/)
milik [hemanth](https://github.com/hemanth/) dan telah dikatakan berhasil karena
[kontribusi](https://github.com/hemanth/functional-programming-jargon/graphs/contributors)
yang luar biasa.