Saya telah membaca buku Learn You a Haskell sampai pada titik di mana mereka memperkenalkan Monads dan hal-hal seperti Just a. Ini sangat berlawanan dengan intuisi saya sehingga saya merasa ingin berhenti mencoba mempelajarinya.
Tetapi saya benar-benar ingin mencoba.
Saya bertanya-tanya apakah saya setidaknya dapat menghindari konsep-konsep lanjutan untuk sementara waktu dan baru mulai menggunakan bagian lain dari bahasa untuk melakukan banyak tugas praktis dengan bagian-bagian yang lebih mendasar dari Haskell, yaitu fungsi, IO standar, penanganan file, antarmuka database dan sejenisnya.
Apakah ini pendekatan yang masuk akal untuk mempelajari cara menggunakan Haskell?
Jawaban:
Pertama mari kita bedakan antara mempelajari konsep-konsep abstrak dan mempelajari contoh-contoh spesifiknya .
Anda tidak akan terlalu jauh mengabaikan semua contoh spesifik, karena alasan sederhana bahwa mereka benar-benar ada di mana-mana. Faktanya, abstraksi ada sebagian besar karena mereka menyatukan hal-hal yang akan Anda lakukan dengan contoh-contoh spesifik.
Abstraksi itu sendiri, di sisi lain, tentu berguna , tetapi mereka tidak segera diperlukan. Anda bisa mengabaikan abstraksi sepenuhnya dan hanya menggunakan berbagai jenis secara langsung. Anda akan ingin memahami mereka pada akhirnya, tetapi Anda selalu dapat kembali lagi nanti. Bahkan, saya hampir dapat menjamin bahwa jika Anda melakukan itu, ketika Anda kembali ke sana Anda akan menampar dahi Anda dan bertanya-tanya mengapa Anda menghabiskan semua waktu itu melakukan hal-hal dengan cara yang sulit daripada menggunakan alat tujuan umum yang nyaman.
Ambil
Maybe a
sebagai contoh. Itu hanya tipe data:Semuanya mendokumentasikan diri; ini merupakan nilai opsional. Entah Anda memiliki "hanya" sesuatu jenis
a
, atau Anda tidak punya apa-apa. Katakanlah Anda memiliki fungsi pencarian, yang kembaliMaybe String
untuk mewakili mencariString
nilai yang mungkin tidak ada. Jadi Anda mencocokkan pola pada nilai untuk melihat yang mana itu:Itu saja!
Sungguh, tidak ada lagi yang Anda butuhkan. Tidak ada
Functor
s atauMonad
s atau apa pun. Itu mengungkapkan cara umum menggunakanMaybe a
nilai ... tapi itu hanya idiom, "pola desain", apa pun yang Anda ingin menyebutnya.Satu-satunya tempat Anda benar-benar tidak bisa menghindarinya sepenuhnya adalah dengan
IO
, tetapi itu adalah kotak hitam yang misterius, jadi tidak ada gunanya mencoba memahami apa artinya sebagaiMonad
atau apa pun.Sebenarnya, inilah lembar contekan untuk semua yang benar - benar perlu Anda ketahui
IO
untuk saat ini:Jika sesuatu memiliki tipe
IO a
, itu berarti prosedur yang melakukan sesuatu dan mengeluarkana
nilai.Ketika Anda memiliki blok kode menggunakan
do
notasi, tulis sesuatu seperti ini:... berarti menjalankan prosedur di sebelah kanan
<-
, dan menetapkan hasilnya ke nama di sebelah kiri.Sedangkan jika Anda memiliki sesuatu seperti ini:
... itu berarti menetapkan nilai ekspresi polos (bukan prosedur) di sebelah kanan
=
untuk ke nama di sebelah kiri.Jika Anda meletakkan sesuatu di sana tanpa menetapkan nilai, seperti ini:
... artinya menjalankan prosedur dan mengabaikan apa pun yang dikembalikan. Beberapa prosedur memiliki tipe
IO ()
-()
tipe ini adalah semacam placeholder yang tidak mengatakan apa-apa, sehingga hanya berarti prosedur melakukan sesuatu dan tidak mengembalikan nilai. Agak sepertivoid
fungsi dalam bahasa lain.Menjalankan prosedur yang sama lebih dari satu kali dapat memberikan hasil yang berbeda; itu semacam ide. Inilah sebabnya mengapa tidak ada cara untuk "menghapus"
IO
dari nilai, karena sesuatu di dalamIO
bukan nilai, itu adalah prosedur untuk mendapatkan nilai.Baris terakhir dalam sebuah
do
blok harus berupa prosedur sederhana tanpa penugasan, di mana nilai balik dari prosedur itu menjadi nilai balik untuk seluruh blok. Jika Anda ingin nilai kembali menggunakan beberapa nilai yang telah ditetapkan,return
fungsi tersebut mengambil nilai polos dan memberi Anda prosedur larangan yang mengembalikan nilai itu.Selain itu, tidak ada yang istimewa tentang
IO
; prosedur-prosedur ini sebenarnya adalah nilai-nilai sederhana itu sendiri, dan Anda dapat menyebarkannya dan menggabungkannya dengan cara yang berbeda. Hanya ketika mereka dieksekusi dido
blok yang disebut di suatu tempat dimain
mana mereka melakukan apa pun.Jadi, dalam sesuatu seperti program contoh stereotip yang benar-benar membosankan ini:
... Anda dapat membacanya seperti program penting. Kami mendefinisikan prosedur bernama
hello
. Ketika dieksekusi, terlebih dahulu ia menjalankan prosedur untuk mencetak pesan yang menanyakan nama Anda; selanjutnya ia menjalankan prosedur yang membaca sebaris input, dan memberikan hasilnya kepadaname
; lalu memberikan ekspresi pada namamsg
; lalu ia mencetak pesan; lalu mengembalikan nama pengguna sebagai hasil dari seluruh blok. Karenaname
aString
, ini berartihello
prosedur yang mengembalikan aString
, sehingga memiliki tipeIO String
. Dan sekarang Anda dapat menjalankan prosedur ini di tempat lain, sama seperti itu dijalankangetLine
.Pfff, monad. Siapa yang butuh mereka?
sumber
Mereka sangat penting. Tanpa mereka, terlalu mudah untuk menggunakan Haskell sebagai bahasa imperatif lainnya, dan meskipun Simon Peyton Jones pernah memanggil Haskell, "bahasa pemrograman imperatif terbaik di dunia", Anda masih melewatkan bagian terbaiknya.
Monads, Monad Transforms, Monoids, Functors, Functors Applicative, Functors Contravarient, Arrows, Categories, dll, adalah pola desain. Setelah Anda memasukkan hal spesifik yang Anda buat menjadi salah satunya, Anda dapat memanfaatkan banyak sekali fungsi yang ditulis secara abstrak. Kelas-tipe ini tidak hanya membuat Anda bingung, mereka ada di sana untuk membuat hidup Anda lebih mudah dan membuat Anda lebih produktif. Mereka, menurut pendapat saya, alasan terbesar untuk keringkasan kode Haskell yang baik.
sumber
Apakah ini benar-benar diperlukan jika Anda hanya ingin menjalankan sesuatu? Tidak.
Apakah perlu jika Anda ingin menulis program Haskell idiomatik yang indah? Benar.
Saat memprogram di Haskell, ada baiknya Anda mengingat dua hal:
Jenis sistem ada untuk membantu Anda. Jika Anda menyusun program Anda dari kode tipeclass-sangat polimorfik, sangat sering Anda bisa masuk ke situasi yang indah di mana jenis fungsi yang Anda inginkan akan memandu Anda ke (satu satu!) Implementasi yang benar .
Berbagai perpustakaan yang tersedia dikembangkan dengan menggunakan prinsip # 1.
Jadi ketika menulis sebuah program di Haskell, saya mulai dengan menulis tipenya. Lalu saya mulai lagi dan menulis beberapa jenis yang lebih umum (dan jika itu bisa menjadi contoh dari kacamata yang ada, semua lebih baik). Lalu saya menulis beberapa fungsi yang memberi saya nilai dari tipe yang saya inginkan. (Lalu saya bermain dengan mereka
ghci
dan mungkin menulis beberapa tes Periksa cepat.) Dan akhirnya saya rekatkan semuanyamain
.Dimungkinkan untuk menulis Haskell jelek yang baru saja menjalankan sesuatu. Tetapi ada banyak lagi yang harus dipelajari setelah Anda mencapai tahap itu.
Semoga berhasil!
sumber