mengapa cerita rakyat dan ramda begitu berbeda?


96

Saya belajar javascript FP dengan membaca buku DrBoolean .

Saya mencari-cari perpustakaan pemrograman fungsional. Saya menemukan Ramda dan Folktale. Keduanya mengklaim sebagai perpustakaan pemrograman fungsional.

Tapi mereka sangat berbeda:

  • Ramda tampaknya berisi fungsi utilitas untuk menangani daftar: peta, reduksi, filter, dan fungsi murni: kari, tulis. Itu tidak mengandung apapun yang berhubungan dengan monad, functor.

  • Namun cerita rakyat tidak mengandung utilitas untuk daftar atau fungsi. Tampaknya menerapkan beberapa struktur aljabar dalam javascript seperti monad: Mungkin, Tugas ...

Sebenarnya saya menemukan lebih banyak perpustakaan, semuanya tampaknya termasuk dalam dua kategori. Garis bawah dan lodash seperti Ramda. Fantasy-land, pointfree-fantasy seperti cerita rakyat.

Dapatkah perpustakaan yang sangat berbeda ini disebut fungsional , dan jika demikian, apa yang membuat setiap perpustakaan fungsional?


1
gunakan apa yang sesuai dengan kebutuhan dan gaya Anda dan didokumentasikan dengan baik
charlietfl

1
Saya telah menemukan sebenarnya ada tiga arti yang umumnya dimaksudkan untuk "pemrograman fungsional", terutama di JS. 1. menggunakan fungsi murni tingkat tinggi pada himpunan seperti array., Ex [1,2,3].map(fnSquare).reduce(fnSum)2. sebagian besar struktur akademis "look ma no var " Y-combinator-esque. 3. menggunakan Function.prototypeuntuk mengubah perilaku fungsi lain, sepertivar isMissingID=fnContains.partial("id").negate();
dandavis

10
Seorang penulis Ramda di sini: Ramda adalah pustaka utilitas tingkat rendah. Ini dimaksudkan untuk membuat gaya fungsional tertentu lebih sederhana di JS, terutama bekerja dengan menyusun fungsi. Ramda bekerja dengan baik dengan spesifikasi FantasyLand, termasuk implementasi seperti Folktale. Perpustakaan tersebut dirancang untuk tujuan yang agak berbeda. Mereka dibangun dengan mengenali tipe data abstrak umum dan memungkinkan akses yang konsisten ke mereka: hal-hal seperti Monoids, Functors, dan Monads. Ramda akan bekerja dengan mereka, dan memiliki proyek sampingan untuk membuatnya, tetapi, seperti yang Anda katakan, fokusnya sangat berbeda.
Scott Sauyet

1
@KeithNicholas: Ya, ada Ruang Gitter
Scott Sauyet

2
Lihatlah juga Sanctuary - github.com/plaid/sanctuary Ini didasarkan pada ramda tetapi juga mencakup jenis tanah fantasi.
arcseldon

Jawaban:


180

Fitur Fungsional

Tidak ada batasan yang jelas tentang apa yang mendefinisikan pemrograman fungsional atau pustaka fungsional. Beberapa fitur bahasa fungsional dibangun ke dalam Javascript:

  • Fungsi kelas satu, tingkat lebih tinggi
  • Fungsi Lambdas / Anonymous, dengan closure

Yang lainnya mungkin dilakukan dalam Javascript dengan hati-hati:

  • Kekekalan
  • Transparansi Referensial

Yang lain lagi adalah bagian dari ES6, dan sebagian atau seluruhnya tersedia sekarang:

  • Fungsi kompak, bahkan singkat
  • Rekursi berperforma melalui pengoptimalan tail-call

Dan ada banyak lainnya yang benar-benar di luar jangkauan normal Javascript:

  • Pencocokan pola
  • Evaluasi malas
  • Homoikonisitas

Sebuah perpustakaan, kemudian, dapat memilih jenis fitur yang ingin didukungnya dan masih dapat disebut "fungsional".

Spesifikasi negeri fantasi

Fantasy-land adalah spesifikasi untuk sejumlah tipe standar yang ditransfer dari Teori Kategori matematika dan Aljabar Abstrak ke pemrograman fungsional, tipe-tipe seperti Monoid , Functor , dan Monad . Jenis ini cukup abstrak, dan memperluas pengertian yang mungkin lebih dikenal. Functor, misalnya, adalah container yang dapat mapdiayunkan dengan suatu fungsi, seperti cara mapped over menggunakan array Array.prototype.map.

Cerita rakyat

Cerita rakyat adalah kumpulan jenis yang menerapkan berbagai bagian spesifikasi tanah Fantasi dan sekumpulan kecil fungsi utilitas pendamping. Jenis-jenis ini adalah hal-hal seperti Maybe , Either , Task (sangat mirip dengan apa yang di tempat lain disebut Masa Depan, dan sepupu yang lebih sah dari sebuah Janji), dan Validasi

Cerita rakyat mungkin adalah implementasi paling terkenal dari spesifikasi Fantasy-land, dan itu sangat dihormati. Tetapi tidak ada yang namanya implementasi definitif atau default; Fantasy-land hanya menentukan tipe abstrak, dan implementasi tentu saja harus menciptakan tipe konkret seperti itu. Klaim cerita rakyat sebagai pustaka fungsional jelas: ia menyediakan tipe data yang biasanya ditemukan dalam bahasa pemrograman fungsional, yang membuatnya jauh lebih mudah untuk memprogram secara fungsional.

Contoh ini, dari dokumentasi Cerita Rakyat ( catatan : tidak di versi terbaru dari dokumen), menunjukkan bagaimana itu dapat digunakan:

// We load the library by "require"-ing it
var Maybe = require('data.maybe')

// Returns Maybe.Just(x) if some `x` passes the predicate test
// Otherwise returns Maybe.Nothing()
function find(predicate, xs) {
  return xs.reduce(function(result, x) {
    return result.orElse(function() {
      return predicate(x)?    Maybe.Just(x)
      :      /* otherwise */  Maybe.Nothing()
    })
  }, Maybe.Nothing())
}

var numbers = [1, 2, 3, 4, 5]

var anyGreaterThan2 = find(function(a) { return a > 2 }, numbers)
// => Maybe.Just(3)

var anyGreaterThan8 = find(function(a) { return a > 8 }, numbers)
// => Maybe.Nothing

Ramda

Ramda (penafian: Saya salah satu penulis) adalah jenis perpustakaan yang sangat berbeda. Ini tidak memberikan tipe baru untuk Anda. 1 Sebaliknya, ia menyediakan fungsi untuk membuatnya lebih mudah dioperasikan pada tipe yang sudah ada. Itu dibangun di sekitar gagasan menyusun fungsi yang lebih kecil menjadi yang lebih besar, bekerja dengan data yang tidak dapat diubah, untuk menghindari efek samping.

Ramda beroperasi terutama pada daftar, tetapi juga pada objek, dan terkadang pada String. Ia juga mendelegasikan banyak seruannya sedemikian rupa sehingga ia akan beroperasi dengan dongeng atau implementasi tanah Fantasi lainnya. Misalnya, mapfungsi Ramda , beroperasi mirip dengan yang di Array.prototype, jadi R.map(square, [1, 2, 3, 4]); //=> [1, 4, 9, 16]. Tetapi karena Folktale Maybemengimplementasikan Functorspesifikasi Fantasy-land , yang juga menentukan peta, Anda juga dapat menggunakan Ramda mapdengannya:

R.map(square, Maybe.Just(5)); //=> Maybe.Just(25);
R.map(square, Maybe.Nothing); //=> Maybe.Nothing

Klaim Ramda sebagai pustaka fungsional terletak pada kemudahan untuk membuat fungsi, tidak pernah mengubah data Anda, dan hanya menyajikan fungsi murni. Penggunaan khas Ramda adalah untuk membangun fungsi yang lebih kompleks dengan membuat yang lebih kecil, seperti yang terlihat dalam artikel tentang filosofi Ramda.

// :: [Comment] -> [Number]  
var userRatingForComments = R.pipe(
    R.pluck('username')      // [Comment] -> [String]
    R.map(R.propOf(users)),  // [String] -> [User]
    R.pluck('rating'),       // [User] -> [Number]
);

Perpustakaan Lainnya

Sebenarnya saya menemukan lebih banyak perpustakaan, semuanya tampaknya termasuk dalam dua kategori. menggarisbawahi, lodash sangat mirip dengan Ramda. Fantasy-land, pointfree-fantasy seperti cerita rakyat.

Itu tidak terlalu akurat. Pertama-tama, Fantasy-land hanyalah spesifikasi yang dapat diputuskan oleh perpustakaan untuk diterapkan untuk berbagai jenis. Cerita rakyat adalah salah satu dari banyak penerapan spesifikasi itu, mungkin yang terbaik, pasti salah satu yang paling matang. Pointfree-fantasy dan ramda-fantasy adalah yang lainnya, dan masih banyak lagi .

Garis bawah dan lodash secara dangkal seperti Ramda karena mereka adalah perpustakaan tas tangan, menyediakan sejumlah besar fungsi dengan kohesi yang jauh lebih sedikit daripada sesuatu seperti Cerita Rakyat. Dan bahkan fungsionalitas tertentu sering tumpang tindih dengan Ramda. Namun secara lebih mendalam, Ramda memiliki perhatian yang sangat berbeda dengan perpustakaan tersebut. Sepupu terdekat Ramda ini mungkin perpustakaan seperti FKit , Fnuc , dan Wu.js .

Bilby termasuk dalam kategorinya sendiri, menyediakan sejumlah alat seperti yang disediakan oleh Ramda dan beberapa jenis yang sesuai dengan Fantasy-land. (Penulis Bilby adalah penulis asli Fantasy-land juga.)

Panggilanmu

Semua perpustakaan ini berhak disebut fungsional, meskipun mereka sangat bervariasi dalam pendekatan fungsional dan tingkat komitmen fungsional.

Beberapa dari perpustakaan ini sebenarnya bekerja sama dengan baik. Ramda harus bekerja dengan baik dengan cerita rakyat atau implementasi tanah fantasi lainnya. Karena keprihatinan mereka hampir tidak tumpang tindih, mereka benar-benar tidak berkonflik, tetapi Ramda berbuat cukup untuk membuat interoperasinya relatif lancar. Ini mungkin kurang benar untuk beberapa kombinasi lain yang dapat Anda pilih, tetapi sintaks fungsi ES6 yang lebih sederhana juga dapat mengurangi kesulitan dalam mengintegrasikan.

Pilihan pustaka, atau bahkan gaya pustaka yang akan digunakan, akan bergantung pada proyek dan preferensi Anda. Ada banyak pilihan bagus yang tersedia, dan jumlahnya terus bertambah, dan banyak di antaranya yang meningkat pesat. Ini saat yang tepat untuk melakukan pemrograman fungsional di JS.


1 Nah, ada proyek sampingan , ramda-fantasi melakukan sesuatu yang mirip dengan apa yang dilakukan Folktale, tetapi itu bukan bagian dari pustaka inti.


1
Apakah adil untuk mengatakan ES6 memiliki kemampuan evaluasi malas dengan pengenalan Yield? developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Marcel Lamothe

8
Tidak. yieldMempermudah melakukan jenis pemrosesan daftar malas yang dilakukan oleh Lazyatau lz.js. Tapi itu tidak membantu kemalasan tingkat bahasa. someFunc(a + b)di JS pertama-tama menambahkan nilai adan bkemudian memasok hasil itu sebagai parameter ke someFunc. Persamaan di Haskell tidak melakukan itu. Jika fungsi yang dipanggil tidak pernah menggunakan nilai itu, ia tidak akan pernah melakukan penambahan. Jika akhirnya menggunakannya, itu dianggap sebagai ekspresi yang akan dihitung sampai hasilnya dibutuhkan. Jika Anda tidak pernah melakukan apa pun yang akan memaksanya (seperti IO), ia tidak akan pernah benar-benar melakukan penghitungan.
Scott Sauyet

@ScottSauyet mungkin Anda mungkin berpendapat "evaluasi malas" dalam beberapa bentuk tersedia melalui generator ES6 misalnya - banyak kerangka kerja JS memiliki karakteristik "kemalasan" - RxJs, ImmutableJs dll.
arcseldon

8
Jawaban ini harus menjadi satu bab atau bagian dalam buku DrBoolean. :)
Seth

1
Dokumentasi Ramda cenderung menggunakan "daftar" sebagai singkatan untuk hal terdekat yang ditawarkan JS dengan daftar, larik padat. Ini memiliki karakteristik kinerja yang berbeda dari daftar murni, dan tentu saja API yang agak berbeda, tetapi mereka dapat digunakan untuk tujuan yang hampir sama, dan mereka adalah jenis asli terdekat (tetapi lihat github.com/funkia/list ) yang tersedia untuk Ramda. API, yang secara konseptual ingin bekerja dengan daftar murni. Saya akan memperdebatkan titik array yang tidak benar, karena array gaya-C tidak lebih kanonik daripada yang JS, dan tidak ada yang benar-benar dekat dengan yang matematika, tapi itu poin kecil.
Scott Sauyet
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.