Mengapa lebih baik tidak mengandalkan perubahan kondisi?


16

Pertanyaan ini muncul dari pertanyaan /software/25569/is-haskell-worth-learning

Secara umum beberapa pernyataan yang sering diulang dibuat, tentang bagaimana Haskell meningkatkan keterampilan pengkodean Anda dalam bahasa lain, dan lebih jauh lagi, ini karena Haskell tidak memiliki kewarganegaraan, dan itu adalah hal yang baik.

Mengapa?

Saya pernah melihat seseorang membandingkan ini dengan hanya mengetik dengan tangan kiri, atau mungkin menutup mata Anda selama sehari dan hanya mengandalkan sentuhan. Tentunya ada lebih dari itu?

Apakah itu terkait dengan akses memori perangkat keras, atau sesuatu yang merupakan perolehan kinerja besar?


2
Haskell bersifat akademis. Saya akan menonton beberapa ceramah oleh Rich Hickey tentang Clojure - di sana ia membuat argumen pragmatis pembunuh (mirip dengan 3 poin oleh Javier, tetapi juga dilakukan dengan cara yang sederhana).
Ayub


6
Hanya karena Haskell adalah "akademis" tidak berarti itu tidak praktis atau tidak pragmatis.
Tikhon Jelvis

Jawaban:


17

setidaknya ada tiga keuntungan besar di atas kepala saya:

  1. itu membuat program lebih dekat dengan ekspresi matematika. Dalam matematika, xtidak berubah, Anda tidak tahu apa itu sampai Anda menyelesaikan persamaannya.

  2. Pada akhirnya, ada adalah perubahan negara (setelah semua, itu bagaimana komputer bekerja pada tingkat rendah); tetapi dibatasi oleh bahasa di tempat-tempat tertentu. yang memungkinkan kompiler peluang besar untuk memindahkan kode untuk mengoptimalkannya, karena ia tahu bahwa ia tidak mengubah apa pun yang bergantung pada kode lain.

  3. Kode konkuren tidak perlu disinkronkan untuk mengakses data yang tidak berubah, sehingga konkurensi ditingkatkan, baik dalam sistem memori bersama SMP (semua sistem multicore saat ini), dan pada kluster yang terikat secara longgar.


3
Propoennts pemrograman fungsional menempatkan paling stres # 3, yaitu proramming concurrency lebih mudah.
Mchl

4
@Mchl: Dalam pengalaman saya, mereka lebih menekankan pada "Lebih mudah untuk dipahami dan alasan tentang", yang mana yang sesuai dengan 1. Meskipun saya kira itu mungkin berbeda antara komunitas bahasa.
sepp2k

+1, jawaban yang sangat lengkap. @ sepp2k: saya kira keduanya penting. Penalaran tentang program adalah apa yang kita lakukan setiap hari, dan memang benar bahwa jika Anda tidak perlu memeriksa bahwa negara tidak berubah dalam beberapa fungsi yang tersembunyi, akan lebih mudah untuk membaca hanya metode tingkat tinggi dan menangkap apa yang terjadi. Hardware-wise: karena kita bergerak ke arah multi-core dan multi-prosesor lebih dan lebih (walaupun saya kira itu akan menjadi waktu sebelum komputer di rumah mendapatkan multi-prosesor), memiliki bahasa yang memfasilitasi pemrograman bersamaan adalah premium.
Matthieu M.

Jawaban yang bagus, # 2 adalah apa yang saya anggap sebagai jawabannya, dan meskipun saya sering membaca tentang manfaat multi-pemrosesan, jarang dinyatakan dengan jelas, pekerjaan yang hebat.
ocodo

1
@Ytrtrill, bahasa fungsional tidak unik dalam ketergantungan mereka pada pengumpulan sampah dan pengumpulan sampah jauh lebih mudah ketika Anda berurusan dengan data yang tidak dapat diubah. Melakukan perhitungan pada arsitektur berbasis instruksi berarti mengubah keadaan, itu tidak berarti bahwa bahasa fungsional entah bagaimana lebih sulit untuk diparalelkan. Bahasa fungsional bergoyang paralelisme; mencari data paralel Haskell, ini adalah fitur yang hampir tidak mungkin ditambahkan ke bahasa imperatif.
dan_waterworth

4

Inilah keuntungan lain: kopling yang dikurangi. Jika Anda memiliki kode seperti:

 function doStuff(x) { return x + y;}

dan di tempat lain Anda memiliki:

 function doOtherStuff(x) { y++; return y + x;}

maka kedua fungsi tersebut tergantung secara implisit . Tidak ada cara mudah untuk mengatakan bahwa panggilan doStuffdipengaruhi oleh panggilan doOtherStuff. Tanpa status bisa berubah, Anda harus membuat koneksi eksplisit.

Tentu saja, ini bukan masalah dengan semua status yang bisa berubah - masalah ini adalah status yang bisa berubah. Solusi sebenarnya adalah memiliki kekekalan secara default dan beberapa cara "menandai" dan membatasi keadaan yang bisa berubah ke tempat yang Anda butuhkan.


+1. Banyak programmer berpengalaman tahu untuk tidak menulis kode seperti di atas dan itu bukan langkah besar untuk pergi dari "keadaan berubah-ubah itu buruk dalam situasi ini" menjadi "mari kita secara serius mengurangi jumlah keadaan kita bisa berubah dan menulis lebih fungsional", tetapi ini adalah langkah yang membuat beberapa mengecewakan.
dan_waterworth

2

Jawaban yang disederhanakan adalah: ketika Anda melihat nama dalam bahasa yang murni fungsional, Anda tahu apa nilai yang terkait dengan pencarian sederhana dari definisinya. Jika Anda memiliki variabel yang dapat berubah, Anda hanya dapat mengetahui dari beberapa penugasan mana yang dieksekusi terakhir, jadi Anda juga harus menganalisis aliran kontrol, yang pada gilirannya mungkin bersyarat, membuat Anda memiliki banyak kemungkinan. Untuk mendapatkan ledakan eksponensial, Anda hanya perlu mempertimbangkan bahwa RHS dari tugas itu sendiri tergantung pada variabel, jadi Anda harus menganalisisnya secara rekursif juga.

Intinya dalam analisis di atas adalah bahwa hal itu tidak dapat dipertahankan tanpa komentar yang menjelaskan maksud, invarian, dan semantik: ini mungkin sulit untuk diartikan, dan mungkin sulit untuk memverifikasi semantik dipatuhi dalam kode aktual.

Jawaban ini pada dasarnya adalah perluasan dari poin 1 Javier.

Saya pikir ini juga merupakan penjelasan dari popularitas rezim OO yang curang: dengan OO keadaan yang bisa dirubah diringkas yang membuat analisis jauh lebih mudah dengan menempatkan mutasi pada tingkat tertentu, dan memungkinkan ekspresi dan verifikasi semantik yang jauh lebih kuat.

Setelah mencatat bahwa, pemrograman fungsional bukanlah jawabannya. Jawaban yang tepat adalah sistem yang mendukung pemrograman induktif (fungsional) dan koinduktif (prosedural), sehingga alat yang tepat dapat menangani pemrograman stateless dan stateful. Hanya saja teori konstruktif (fungsional) sudah mapan sedangkan teori manajemen negara masih dalam masa pertumbuhan.


Menggabungkan pemrograman fungsional dan imperatif persis seperti yang dilakukan Haskell - fungsi normal berfungsi sementara komputasi stateful dapat diekspresikan dengan notasi yang memungkinkan Anda mengisolasi dan mengontrol keadaan yang bisa berubah secara hati-hati (antara lain). Inilah sebabnya mengapa bahasa dengan implementasi STM paling praktis adalah Haskell .
Tikhon Jelvis

Do-notation tidak benar-benar ada hubungannya dengan perhitungan stateful per se . Do-notation hanyalah sintaks yang lebih sederhana di atas pipeline fungsi monadik. Perhitungan stateful hanyalah salah satu hal yang dapat diekspresikan menggunakan monad, dan karenanya notasi.
Jonathan Sterling

Pemrograman fungsional dan imperatif campuran adalah apa yang dilakukan hampir setiap bahasa. Haskell mungkin telah menyediakan cara untuk mengisolasi bagian stateful, tapi itu tidak membuatnya menjadi campuran yang tepat: Amal lebih seperti bagaimana seharusnya (IMHO).
Yttrill

2

Sebagai penulis Siege , seorang DBMS yang ditulis dalam Haskell, beberapa orang mungkin menganggap pandangan saya tentang keadaan yang bisa berubah bertentangan. Saya berharap untuk menunjukkan sebaliknya.

Tujuan dari keadaan yang bisa berubah adalah untuk menggambarkan keadaan saat ini di mana suatu sistem berada. Katakanlah Anda memiliki blog dan didukung oleh database, database tersebut menjelaskan posting yang Anda miliki di blog Anda pada titik waktu di mana Anda bertanya Itu. Berapa banyak posting yang ada saat ini?

Bandingkan hal ini dengan keadaan abadi yang digunakan untuk menyampaikan fakta. Berapa banyak posting di sana pada 12 Agustus?

Fakta mudah dipikirkan, keadaan tidak bisa berubah tidak bisa. Namun, keadaan yang bisa berubah bukanlah efek jahat yang tidak murni yang harus dibuang dari jangkauan pikiran kita; kita sering membutuhkannya untuk hidup berdampingan dalam dunia yang bisa berubah yang kita tinggali, kita hanya perlu menggunakannya lebih hemat.

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.