Oleh karena itu, katakanlah, query database atau menulis file tidak dapat dilakukan dengan gaya fungsional murni menurut definisi. Itu misalnya, adalah salah satu alasan kita membutuhkan monad.
Tidak ada yang "membutuhkan" monad, itu hanya satu cara untuk menggambarkan berbagai hal. Bahkan, itu mungkin bukan cara terbaik. Beberapa bentuk efek pengetikan , tipe keunikan , atau sistem yang didasarkan pada logika linier penuh tampak lebih persuasif dalam teori tetapi semuanya lebih radikal dari sistem tipe yang terkenal dan lebih rumit untuk diekspresikan. IO monadik seperti yang ditemukan di Haskell adalah kompromi antara kegunaan dan kesederhanaan, karena pada dasarnya memodelkan pemrograman yang sangat penting dengan cara yang hidup berdampingan dengan mudah dengan sistem tipe gaya ML yang sudah digunakan dalam bahasa.
Pertanyaannya adalah - mengapa kita menganggap output STDOUT sebagai sesuatu yang tidak murni? Ya, pembuat file apa pun berisiko - kami tidak pernah dapat memastikan bahwa data akan selalu ditulis. Tapi bagaimana dengan STDOUT? Mengapa kita harus menganggapnya sebagai sesuatu yang tidak dapat diandalkan? Apakah evaluasi itu sendiri tidak dapat diandalkan? Maksud saya, kita selalu dapat menarik pelatuk dan dengan demikian, mengganggu perhitungan.
Tidak, dan kami tidak. Input ke, dan output dari, program secara keseluruhan dapat dengan mudah dianggap sebagai argumen dan hasil dari memperlakukan seluruh program sebagai satu fungsi murni yang besar. Selama itu mencetak hal yang sama ke stdout jika Anda memberinya hal yang sama dari stdin, itu masih fungsi murni. Bahkan, sebelum memperkenalkan IO monadik, Haskell menggunakan sistem I / O berbasis aliran yang menggunakan aliran malas murni untuk input dan output. Itu menjatuhkannya karena itu tampaknya menyakitkan untuk digunakan, yang mungkin memberi Anda beberapa ide mengapa Anda belum pernah mendengar hal seperti ini. :]
Untuk menjelaskan maksudnya dengan cara yang lebih konyol, pertimbangkan bahasa esoteris minimalis, Lazy K :
Lazy K adalah bahasa pemrograman fungsional yang dikumpulkan secara sampah dan transparan, dengan sistem I / O berbasis aliran yang sederhana.
Yang membedakan Lazy K dari bahasa lain adalah hampir tidak adanya fitur lainnya. Sebagai contoh, ia tidak menawarkan sistem tipe polimorfik Hindley-Milner yang terintegrasi. Itu tidak dikirim dengan perpustakaan standar yang luas dengan dukungan untuk pemrograman GUI platform-independen dan binding ke bahasa lain. Pustaka semacam itu tidak dapat ditulis karena, antara lain, Lazy K tidak menyediakan cara untuk mendefinisikan atau merujuk ke fungsi apa pun selain built-in. Ketidakmampuan ini dilengkapi dengan kurangnya dukungan untuk angka, string, atau tipe data lainnya. Namun demikian, Lazy K adalah Turing-complete
(...)
Program-program Lazy K hidup dalam ranah Platonis abadi yang sama dengan fungsi matematika, apa yang disebut halaman Unlambda "ranah yang diberkati dari kalkulus lambda murni yang tidak diketik." Sama seperti pengumpulan sampah menyembunyikan proses manajemen memori dari programmer, sehingga transparansi referensial menyembunyikan proses evaluasi. Fakta bahwa beberapa perhitungan diperlukan untuk melihat gambar set Mandelbrot, atau untuk "menjalankan" program Lazy K, adalah detail implementasi. Itulah esensi pemrograman fungsional.
(...)
Bagaimana menangani input dan output dalam bahasa tanpa efek samping? Dalam arti tertentu, input dan output bukanlah efek samping; mereka, jadi untuk berbicara, efek depan dan belakang. Demikian juga di Lazy K, di mana program hanya diperlakukan sebagai fungsi dari ruang input yang mungkin ke ruang output yang mungkin.
Saya ragu Anda akan menemukan bahasa yang lebih murni fungsional dari itu!
Perlu diingat, bahwa hal-hal di atas hanya berlaku pada dasarnya mengambil input dan output dari fungsi murni dan menghubungkannya ke stdin / stdout "eksternal" dengan cara tertentu. Ada perbedaan besar antara itu dan memiliki akses ke sistem I / O primitif tingkat nyata. Detail implementasi dari membaca dan menulis ke aliran dapat bocor pengotor kecuali jika dienkapsulasi dengan cermat.
Saya berharap ini adalah alasan utama Anda tidak dapat melakukan ini secara langsung di Haskell - kasing yang masuk akal tipis dibandingkan dengan menggunakan mono IO, dan untuk yang terakhir ada banyak manfaat untuk memiliki akses ke hal yang nyata. Saya percaya itu sebabnya, misalnya, argumen baris perintah untuk program tidak hanya diteruskan sebagai argumen main
, meskipun tampaknya secara intuitif memang seharusnya demikian.
Anda dapat memulihkan versi minimal sesuatu seperti ini di program tertentu, meskipun - hanya menangkap argumen sebagai nilai-nilai murni dan kemudian menggunakan yang interact
fungsi untuk sisa program anda.