Saya hanya tidak mendapatkan masalah apa yang mereka pecahkan.
haskell
pragmatism
monad
Pekerjaan
sumber
sumber
Jawaban:
Monad tidak baik atau buruk. Mereka memang begitu. Mereka alat yang digunakan untuk memecahkan masalah seperti banyak konstruksi bahasa pemrograman lainnya. Satu aplikasi yang sangat penting dari mereka adalah untuk membuat hidup lebih mudah bagi programmer yang bekerja dalam bahasa yang murni fungsional. Tetapi mereka berguna dalam bahasa non-fungsional; hanya saja orang jarang menyadari bahwa mereka menggunakan Monad.
Apa itu Monad? Cara terbaik untuk memikirkan Monad adalah sebagai pola desain. Dalam kasus I / O, Anda mungkin bisa menganggapnya sebagai sedikit lebih dari pipa yang dimuliakan di mana negara global adalah apa yang dilewati di antara tahapan.
Misalnya, mari kita ambil kode yang Anda tulis:
Ada banyak hal yang terjadi di sini daripada yang terlihat. Misalnya, Anda akan melihat bahwa
putStrLn
memiliki tanda tangan berikut:putStrLn :: String -> IO ()
. Kenapa ini?Pikirkan seperti ini: mari kita berpura-pura (demi kesederhanaan) bahwa stdout dan stdin adalah satu-satunya file yang dapat kita baca dan tulis. Dalam bahasa imperatif, ini bukan masalah. Tetapi dalam bahasa fungsional, Anda tidak dapat mengubah keadaan global. Fungsi hanyalah sesuatu yang mengambil nilai (atau nilai) dan mengembalikan nilai (atau nilai). Salah satu cara mengatasi hal ini adalah dengan menggunakan negara global sebagai nilai yang masuk dan keluar dari setiap fungsi. Jadi, Anda bisa menerjemahkan baris kode pertama menjadi sesuatu seperti ini:
... dan kompiler akan tahu untuk mencetak apa pun yang ditambahkan ke elemen kedua
global_state
. Sekarang saya tidak tahu tentang Anda, tetapi saya akan benci untuk memprogram seperti itu. Cara ini dibuat lebih mudah adalah dengan menggunakan Monads. Di Monad, Anda meneruskan nilai yang mewakili semacam keadaan dari satu tindakan ke tindakan berikutnya. Inilah sebabnya mengapaputStrLn
memiliki jenis pengembalianIO ()
: mengembalikan negara global baru.Jadi mengapa kamu peduli? Nah, kelebihan pemrograman fungsional daripada program imperatif telah diperdebatkan sampai mati di beberapa tempat, jadi saya tidak akan menjawab pertanyaan itu secara umum (tetapi lihat makalah ini jika Anda ingin mendengar kasus pemrograman fungsional). Namun untuk kasus khusus ini, mungkin membantu jika Anda memahami apa yang ingin dicapai Haskell.
Banyak programmer merasa bahwa Haskell mencoba untuk mencegah mereka dari menulis kode penting atau menggunakan efek samping. Itu tidak sepenuhnya benar. Pikirkan seperti ini: bahasa imperatif adalah bahasa yang memungkinkan efek samping secara default, tetapi memungkinkan Anda untuk menulis kode fungsional jika Anda benar-benar ingin (dan bersedia untuk berurusan dengan beberapa contortions yang akan memerlukan). Haskell murni berfungsi secara default, tetapi memungkinkan Anda untuk menulis kode penting jika Anda benar-benar ingin (yang Anda lakukan jika program Anda berguna). Intinya bukan untuk membuatnya sulit untuk menulis kode yang memiliki efek samping. Ini untuk memastikan Anda secara eksplisit memiliki efek samping (dengan sistem tipe yang memberlakukan ini).
sumber
goto
(sebagai argumen untuk pemrograman terstruktur) sedikit kemudian di koran, mengkarakterisasi argumen seperti "sia-sia." Namun tidak satupun dari kita diam-diam berharap untukgoto
kembali. Hanya saja Anda tidak bisa berdebat yanggoto
tidak perlu bagi orang yang menggunakannya secara luas.Saya akan menggigit !!! Monads sendiri sebenarnya bukan raison d'etre untuk Haskell (versi awal Haskell bahkan tidak memilikinya).
Pertanyaan Anda agak seperti mengatakan "C ++ ketika saya melihat sintaks, saya bosan. Tapi template adalah fitur yang sangat diiklankan dari C ++ jadi saya melihat implementasi dalam bahasa lain".
Evolusi seorang programmer Haskell adalah sebuah lelucon, itu tidak dimaksudkan untuk dianggap serius.
Monad untuk tujuan program di Haskell adalah turunan dari kelas tipe Monad, artinya, itu tipe yang terjadi untuk mendukung serangkaian kecil operasi tertentu. Haskell memiliki dukungan khusus untuk tipe yang mengimplementasikan kelas tipe Monad, khususnya dukungan sintaksis. Praktis apa hasil ini adalah apa yang telah disebut sebagai "semi-colon yang dapat diprogram". Ketika Anda menggabungkan fungsi ini dengan beberapa fitur Haskell lainnya (fungsi kelas satu, malas secara default) yang Anda dapatkan adalah kemampuan untuk mengimplementasikan hal-hal tertentu sebagai perpustakaan yang secara tradisional dianggap sebagai fitur bahasa. Misalnya, Anda dapat menerapkan mekanisme pengecualian. Anda dapat menerapkan dukungan untuk kelanjutan dan coroutine sebagai perpustakaan. Haskell, bahasa tidak memiliki dukungan untuk variabel yang bisa berubah:
Anda bertanya tentang "Mungkin / Identity / Safe Division monads ???". Mungkin monad adalah contoh bagaimana Anda menerapkan (sangat sederhana, hanya satu pengecualian) penanganan pengecualian sebagai perpustakaan.
Anda benar, menulis pesan dan membaca input pengguna tidak terlalu unik. IO adalah contoh buruk "monad sebagai fitur".
Tetapi untuk beralih, satu "fitur" dengan sendirinya (misalnya Monads) dalam isolasi dari sisa bahasa tidak serta merta langsung tampak berguna (fitur baru C ++ 0x yang hebat adalah referensi nilai, tidak berarti Anda dapat mengambil mereka keluar dari konteks C ++ karena sintaks membuat Anda bosan dan perlu melihat utilitas). Bahasa pemrograman bukanlah sesuatu yang Anda dapatkan dengan melemparkan banyak fitur ke dalam sebuah ember.
sumber
Pemrogram semua menulis program, tetapi kesamaan berakhir di sana. Saya pikir programmer berbeda jauh lebih dari kebanyakan programmer bisa bayangkan. Ambil "pertempuran" lama, seperti mengetik variabel statis vs tipe runtime saja, skrip vs dikompilasi, gaya-C vs berorientasi objek. Anda akan merasa mustahil untuk secara rasional berpendapat bahwa satu kubu lebih rendah, karena beberapa dari mereka mengeluarkan kode yang sangat baik dalam beberapa sistem pemrograman yang tampaknya tidak berguna atau bahkan tidak dapat digunakan oleh saya.
Saya pikir orang yang berbeda hanya berpikir secara berbeda, dan jika Anda tidak tergoda oleh gula sintaksis atau terutama abstraksi yang hanya ada untuk kenyamanan dan benar-benar memiliki biaya runtime yang signifikan, maka dengan segala cara menjauh dari bahasa tersebut.
Namun saya akan merekomendasikan bahwa Anda setidaknya mencoba membiasakan diri dengan konsep yang Anda menyerah. Saya tidak membenci seseorang yang sangat pro-murni-C, asalkan mereka benar-benar mengerti apa pentingnya ekspresi lambda. Saya curiga bahwa sebagian besar dari mereka tidak akan langsung menjadi penggemar, tetapi paling tidak itu akan ada di benak mereka ketika mereka menemukan masalah sempurna apa yang akan terjadi, jadi jauh lebih mudah untuk diselesaikan dengan lambda.
Dan, di atas semua itu, cobalah untuk tidak merasa terganggu oleh ucapan fanboy, terutama oleh orang-orang yang tidak benar-benar tahu apa yang mereka bicarakan.
sumber
Haskell memberlakukan Transparansi Referensial : diberikan parameter yang sama, setiap fungsi selalu mengembalikan hasil yang sama, tidak peduli berapa kali Anda memanggil fungsi itu.
Itu berarti, misalnya, bahwa pada Haskell (dan tanpa Monads) Anda tidak dapat mengimplementasikan generator nomor acak. Di C ++ atau Java Anda bisa melakukannya menggunakan variabel global, menyimpan nilai "seed" perantara dari generator acak.
Di Haskell, mitra variabel global adalah Monads.
sumber
Random
objek.Agak pertanyaan lama tapi itu benar-benar bagus, jadi saya akan jawab.
Anda dapat menganggap monads sebagai blok kode yang Anda miliki kendali penuh atas cara mereka dieksekusi: apa yang harus dikembalikan setiap baris kode, apakah eksekusi harus berhenti pada titik mana pun, apakah beberapa pemrosesan lain harus terjadi di antara setiap baris.
Saya akan memberikan beberapa contoh hal-hal yang dimungkinkan oleh monad yang akan sulit sebaliknya. Tak satu pun dari contoh-contoh ini ada di Haskell, hanya karena pengetahuan Haskell saya agak goyah, tetapi mereka semua adalah contoh bagaimana Haskell mengilhami penggunaan monad.
Parser
Biasanya, jika Anda ingin menulis semacam parser, katakanlah untuk mengimplementasikan bahasa pemrograman, Anda harus membaca spesifikasi BNF dan menulis sejumlah besar kode gila untuk menguraikannya, atau Anda harus menggunakan kompiler kompiler seperti Flex, Bison, yacc dll. Tetapi dengan monads, Anda dapat membuat semacam "kompiler parser" tepat di Haskell.
Parser tidak dapat dilakukan tanpa monad atau bahasa tujuan khusus seperti yacc, bison dll.
Misalnya, saya mengambil spesifikasi bahasa BNF untuk protokol IRC :
Dan mengubahnya menjadi sekitar 40 baris kode dalam F # (yang merupakan bahasa lain yang mendukung monads):
Sintaks monad F # sangat jelek dibandingkan dengan Haskell, dan saya mungkin bisa sedikit memperbaiki ini - tetapi intinya untuk dibawa pulang adalah secara struktural, kode parser identik dengan BNF. Tidak hanya ini akan membutuhkan lebih banyak pekerjaan tanpa monad (atau generator parser), itu akan hampir tidak memiliki kemiripan dengan spesifikasi, dan dengan demikian mengerikan untuk dibaca dan dipelihara.
Multitasking khusus
Biasanya, multitasking dianggap sebagai fitur OS - tetapi dengan monads, Anda dapat menulis penjadwal Anda sendiri sehingga setelah setiap instruksi monad, program akan memberikan kontrol ke penjadwal, yang kemudian akan memilih monad lain untuk dieksekusi.
Seorang pria membuat monad "tugas" untuk mengontrol loop game (sekali lagi dalam F #), sehingga daripada harus menulis semuanya sebagai mesin negara yang bekerja pada setiap
Update()
panggilan, ia hanya dapat menulis semua instruksi seolah-olah itu adalah fungsi tunggal .Dengan kata lain, alih-alih harus melakukan sesuatu seperti:
Anda dapat melakukan sesuatu seperti:
LINQ ke SQL
LINQ to SQL sebenarnya adalah contoh dari monad, dan fungsi serupa dapat dengan mudah diimplementasikan di Haskell.
Saya tidak akan membahas detailnya karena saya tidak mengingat semua itu dengan akurat, tetapi Erik Meijer menjelaskannya dengan cukup baik .
sumber
Jika Anda terbiasa dengan pola GoF, monad seperti pola dekorator dan Builder digabungkan, pada steroid, digigit oleh musang radioaktif.
Ada jawaban yang lebih baik di atas, tetapi beberapa manfaat spesifik yang saya lihat adalah:
Monads menghias beberapa tipe inti dengan properti tambahan tanpa mengubah tipe inti. Misalnya, monad mungkin "mengangkat" String dan menambahkan nilai seperti "isWellFormed", "isProfanity" atau "isPalindrome" dll.
sama halnya, monad memungkinkan konglomerasi tipe sederhana menjadi tipe koleksi
Monad memungkinkan pengikatan fungsi yang terlambat ke ruang tingkat tinggi ini
monads memungkinkan pencampuran fungsi dan argumen sewenang-wenang dengan tipe data sewenang-wenang, di ruang orde tinggi
monads memungkinkan memadukan fungsi murni, stateless dengan basis yang tidak murni, stateful, sehingga Anda dapat melacak di mana masalahnya
Contoh akrab dari monad di Jawa adalah Daftar. Dibutuhkan beberapa kelas inti, seperti String, dan "mengangkat" ke ruang monad Daftar, menambahkan informasi tentang daftar. Kemudian ia mengikat fungsi-fungsi baru ke dalam ruang itu seperti get (), getFirst (), add (), empty (), dll.
Pada skala besar, bayangkan bahwa alih-alih menulis program, Anda hanya menulis Builder besar (sebagai pola GoF), dan metode build () pada akhirnya memuntahkan jawaban apa pun yang seharusnya dihasilkan oleh program. Dan Anda dapat menambahkan metode baru ke ProgramBuilder Anda tanpa mengkompilasi ulang kode asli. Itu sebabnya monad adalah model desain yang kuat.
sumber