Apakah sistem tipe Haskell merupakan hambatan untuk memahami pemrograman fungsional? [Tutup]

33

Saya mempelajari Haskell untuk tujuan memahami pemrograman fungsional, dengan harapan bahwa saya akan menerapkan wawasan yang saya peroleh dalam bahasa lain (terutama Groovy, Python, JavaScript.)

Saya memilih Haskell karena saya memiliki kesan bahwa itu sangat fungsional, dan tidak akan membiarkan ketergantungan pada negara.

Saya tidak memilih untuk belajar Haskell karena saya tertarik menavigasi sistem tipe yang sangat kaku.

Pertanyaan saya adalah ini: Apakah sistem tipe yang kuat merupakan produk sampingan yang diperlukan dari bahasa fungsional yang sangat murni, atau apakah ini pilihan desain yang tidak terkait khusus untuk Haskell?

Eric Wilson
sumber
6
Jika Anda tidak ingin mengetikkan apa pun secara eksplisit, Anda tidak perlu mengetik apa pun secara eksplisit. Haskell dapat menyimpulkan jenis dengan baik sendiri. Dan itu tidak seperti Anda akan memiliki variabel tunggal yang berpotensi menyimpan dua jenis yang tidak kompatibel.
Anon.
4
@ Tidak ya, tetapi daftar Anda harus homogen. Percayalah, hal semacam ini bisa menghalangi, bahkan dengan inferensi tipe.
Eric Wilson
13
@FarmBoy dan apa yang salah dengan penggunaan Maybe? Java benar-benar membuat Anda menggunakan Mungkin di semua kelas, yang merupakan hal aneh untuk dilakukan.
alternatif
3
Dan jika Anda benar - benar ingin menggunakan daftar heterogen Anda tentu saja dapat menggunakan tipe data aljabar.
alternatif
1
@ mathepic pada titik ini kami benar-benar kehilangan jejak pertanyaan awal saya, yang merupakan pertanyaan yang benar-benar valid.
Eric Wilson

Jawaban:

40

Saya percaya bahwa memahami sistem tipe Haskell adalah penguat untuk memahami pemrograman fungsional.

Hal tentang pemrograman murni fungsional adalah bahwa tanpa adanya efek samping, yang memungkinkan Anda untuk melakukan segala macam hal secara implisit, pemrograman fungsional murni membuat struktur program Anda jauh lebih eksplisit.

Haskell mencegah Anda mendorong benda-benda di bawah karpet, memaksa Anda untuk berurusan dengan struktur program Anda secara eksplisit, dan itu mengajarkan Anda bahasa untuk menggambarkan struktur ini: bahasa tipe. Memahami tipe, terutama tipe kaya seperti Haskell, akan membuat Anda menjadi programmer yang lebih baik dalam bahasa apa pun.

Jika Haskell tidak diketik dengan kuat, konsep seperti monad, fungsi aplikatif dan sejenisnya tidak akan pernah diterapkan pada pemrograman.

Waquo
sumber
2
Ini adalah jawaban yang baik, tambahan saya adalah bahwa sementara sistem tipe mungkin tampak tidak biasa pada awalnya, nanti ketika Anda mulai mempelajari konsep yang lebih maju, Anda akan melihat bahwa ada hal-hal tertentu yang hanya dapat dilakukan karena kepatuhan terhadap jenis itu. sistem (tambahkan STM dan Data Paralel ke daftar di atas). Hal-hal yang akan menjadi non-starter pada sistem tipe lain cocok secara alami dengan sistem Haskell. Saran saya: tetap menggunakannya sebentar, biarkan meresap dari waktu ke waktu (itu bukan bahasa "menjejalkan").
anon
2
Saya tahu bahwa ini adalah jawaban yang sangat lama, tetapi saya sebenarnya tidak setuju. Saya berpikir bahwa, sejelas mungkin dalam bahasa, sistem tipe, terutama dengan monad seperti State dan Parsec, menyapu BANYAK barang di bawah karpet. Ini sebenarnya sangat mengganggu kemampuan saya untuk mempelajari perpustakaan bahasa.
Savanni D'Gerinel
4
@ SavanniD'Gerinel: Saya pikir dalam jawaban ini "mendorong hal-hal di bawah karpet" tidak berarti menambahkan fungsionalitas implisit (yang Haskell lakukan dengan cara yang terkontrol misalnya melalui monad, dan yang membantu mengurangi boilerplate) tetapi lebih tepatnya mengizinkan beberapa kode lakukan sesuatu yang tidak diharapkan untuk dilakukan. Misalnya: fungsi murni di Haskell tidak akan pernah memiliki efek samping. Periode. Dalam banyak bahasa lain Anda bisa menjanjikan ini dalam dokumentasi fungsi, tetapi tidak ada dalam bahasa Anda yang akan mencegah Anda mendorong beberapa efek samping di suatu tempat dalam kode Anda.
Giorgio
33

Bahasa fungsional yang paling dinamis diketik adalah Skema. Yang mengatakan, sistem tipe Haskell adalah indikator kemurniannya. Ini pertanyaan "bagaimana seseorang mengukur kemurnian?". Sistem tipe Haskell memungkinkan Anda dengan mudah mencegah tindakan tidak murni IO. Untuk melakukan itu, Anda memerlukan sistem tipe statis.

Tetapi katakanlah sistem tipe Haskell tidak ada hubungannya dengan pemrograman fungsional. Masih merupakan puncak keangkuhan untuk mengklaim bahwa sistem tipe tidak akan membantu Anda dalam upaya pendidikan ini. Sistem tipe Haskell kaya dan kompleks, dan lebih menarik jika dibandingkan dengan sistem tipe C ++ dan OCaml.

Apakah itu hambatan? Tidak, saya pikir ini adalah aset. Cobalah untuk mempertimbangkan bagaimana menangani kemalasan Haskell tanpa IOmisalnya.

Logan Capaldo
sumber
8
Sistem tipe +1 Haskell dapat menjadi teman Anda begitu Anda terbiasa.
Larry Coleman
"Untuk melakukan itu, Anda memerlukan sistem tipe statis". Sangat?
Jon Harrop
1
"Semua lebih menarik jika dibandingkan dengan sistem tipe C ++ dan OCaml". Sudahkah Anda mempelajari modul orde tinggi kelas satu OCaml dan sistem objek inferensi dan varian polimorfik yang diketik secara struktural?
Jon Harrop
2
@JonHarrop atau sistem efek atau cara mengukur / mengevaluasi kemurnian. Yap, itu sebabnya menarik untuk membandingkannya. Pilihan berbeda membuat untuk bahasa yang berbeda.
Logan Capaldo
20

Clojure diketik secara dinamis, dan hampir semurni Haskell, jadi ada argumen yang bagus bahwa sistem tipe Haskell lebih merupakan pilihan desain daripada persyaratan mutlak. Keduanya pasti memiliki poin kuat, jadi Anda mungkin ingin mempertimbangkan Clojure jika Anda benar-benar tidak menyukai kekakuan Haskell (tetapi lihat di bawah).

Ketika saya pertama kali mulai menggunakan Haskell, saya menganggap sistem tipe itu mengganggu, dan hanya menoleransi karena inferensi tipe. Saya segera menemukan bahwa banyak jenis kesalahan yang dikompilasi oleh kompiler tentang hal-hal yang tidak akan berhasil walaupun jika kompiler membiarkan saya melakukannya (misalnya, secara tidak sengaja menggunakan peta, bukan concatMap). Saya kemudian menemukan bahwa program yang lulus pemeriksaan tipe biasanya benar, atau paling tidak hampir benar. Saya bahkan memiliki fase malas di mana saya melakukan refactoring dengan mengubah jenis fungsi dan membiarkan kompiler memberi tahu saya apa lagi yang perlu diubah. Akhirnya, saya menyadari bahwa sistem tipe Haskell sebenarnya sangat ekspresif dan mulai merancang program saya di sekitar tipe. Itu adalah Cawan Suci Haskell.

Larry Coleman
sumber
Satu hal yang perlu diperhatikan: Saya belajar pemrograman fungsional menggunakan Skema dan Haskell pada waktu yang hampir bersamaan (yang pertama untuk kelas dan yang terakhir untuk bersenang-senang). Saya menemukan bahwa memahami rekursi jauh lebih mudah dengan pencocokan pola Haskell daripada dengan ifs dan conds dalam Skema, yang saya bayangkan juga dibawa ke Clojure.
Tikhon Jelvis
@Larry Coleman: +1 untuk menggambarkan dengan tepat pengalaman saya sendiri dengan sistem tipe: pertama C ++, lalu Ocaml, dan sekarang bahasa saya sendiri Felix. Ya, saya masih refactor dengan memburu kesalahan kompiler.
Yttrill
8

Sistem tipe Haskell adalah kunci kemampuannya untuk mengisolasi efek dari kode murni. Kecuali jika Anda dapat mengisolasi efek dengan cara lain atau Anda menghilangkan efek seluruhnya, sistem tipe statis yang kuat adalah persyaratan untuk pemrograman fungsional murni.

Haskell adalah contoh bahasa yang sangat bagus dengan sistem tipe statis yang kuat. Jika Anda menginginkan pendidikan yang luas dan menyeluruh dalam ilmu komputer dan desain bahasa pemrograman, Haskell akan menjadi pilihan yang sangat baik sebagai salah satu bahasa yang harus Anda pelajari.

Sistem tipe seharusnya tidak menjadi hambatan besar. Orang yang memprogram cenderung, bahkan ketika menggunakan bahasa yang dinamis, mengikuti konvensi pengetikan yang dapat disandikan menggunakan sistem tipe Haskell. Haskell juga memiliki fitur inferensi tipe yang mengurangi verbositas bila dibandingkan dengan bahasa seperti C ++ dan Java. Ketika Anda mendapatkan pesan kesalahan, kompiler hanya memberi tahu Anda pada waktu kompilasi apa yang akan disampaikan oleh bahasa dengan tipe dinamis saat runtime.

Kebalikan dari sistem tipe dinamis adalah sistem tipe statis, bukan sistem tipe kuat. Sistem tipe yang kuat adalah kebalikan dari sistem tipe yang lemah.

dan_waterworth
sumber
1
Misalnya, C diketik secara statis tetapi lemah. Anda memiliki jenis, tetapi mudah untuk menumbangkan sistem types sepenuhnya, bermain-main dengan representasi spesifik mesin yang mendasari dll. Banyak bahasa yang diketik secara dinamis OTOH diketik dengan sangat kuat - beberapa gips implisit, beberapa cara (jika ada) untuk menumbangkan sistem tipe.
Steve314
4

Ini memberi tahu Anda segera ketika Anda membuat kesalahan bodoh. Ini sangat membantu. Saya telah bekerja di Racket (Skema) musim lalu ini, dan ada beberapa kali saya melewati s-exp yang tidak di-parsing di mana saya mengharapkan parsed ast untuk beberapa fungsi dalam penerjemah saya, dan itu hanya muncul di saya suite tes berukuran sedang. Jika saya memiliki beberapa ketikan statis, itu akan segera menjadi perhatian saya.

Tentu saja, kesalahan logika tidak bisa benar-benar ditangkap oleh sistem tipe, tetapi jumlah cara di mana Anda dapat mengacaukannya sangat berkurang.

Selain itu, ketikkan inferensi memungkinkan Anda mengabaikan sistem jenis jika diinginkan. Masih ada di sana, tetapi tidak memerlukan input aktif dari Anda. Ini masih membantu untuk memahami jenis fungsi Anda, tetapi kode yang benar akan berfungsi dengan baik.

Kemurnian Haskell dikodekan dalam sistem tipenya. IO monad adalah konstruk tingkat tipe yang menghentikan kode tidak murni dari bocor ke fungsi murni, sehingga kemurnian dijamin oleh sistem tipe.

Theo Belaire
sumber
8
Jika Anda pikir Anda dapat mengabaikan sistem tipe Haskell, maka saya pikir Anda belum banyak mengkodekan Haskell.
Eric Wilson
Jangan abaikan sebanyak abaikan saja seperti mengetikkan fungsi, muat di GHCi, dan pergi: t di atasnya. Tetapi Anda masih perlu memercikkan beberapa dariIntegral atau fungsi lain di kadang-kadang.
Theo Belaire
1
Tyr, bahkan dengan inferensi tipe, 90% dari penggunaan dan pengkodean fungsi Haskell membuat hal-hal terkutuk untuk saling menyatu, yang membutuhkan pemahaman tentang sistem tipenya dan pesan kesalahan pengetikan tipikal yang misterius. Bahkan ": t" bukanlah solusi ajaib, hanya langkah pertama untuk memahami cara membuat program dikompilasi.
Andres F.
Ya, beberapa bagian berantakan, saya setuju. Saya benar-benar berpikir bahwa hal-hal numerik dalam pembukaan dapat berdiri untuk dibersihkan dan diperbaiki, karena seperti berdiri, itu berantakan. Tetapi sebagian besar aspek fungsional utama cukup bersih. peta, filter, foldr / l, dan fungsi fungsional menyenangkan lainnya bekerja dengan cukup baik.
Theo Belaire
2

Menjadi bahasa "fungsional", berarti (terlepas dari hal-hal lain) yang fungsinya adalah objek kelas satu dalam bahasa tersebut.

Menjadi bahasa "murni" berarti bahwa fungsi adalah fungsi matematika (berlawanan dengan prosedur) - diberi input yang sama, mereka selalu menghasilkan output yang sama.

"Bahasa fungsional murni" adalah bahasa yang digunakan oleh keduanya di atas. Saya tidak menyadari dari "-murni ly bahasa fungsional".

Sistem tipe yang kuat adalah salah satu cara yang bersih untuk memiliki bahasa yang murni namun praktis. Jenis membantu kompiler mengetahui optimisasi, selain dari form selanjutnya memastikan kebenaran. (Tapi, itu bukan satu-satunya cara - clojure murni, tetapi tidak memiliki sistem tipe sekuat Haskell.)

Jika sistem tipe mengganggu Anda, saya sarankan Anda untuk mencoba bahasa yang lebih dinamis, seperti Skema, atau berkeliling menggunakan sistem inferensi tipe Haskell.

pyNem
sumber
0

Ya, sistem tipe adalah aset yang luar biasa. Akan sangat sulit untuk menggambarkan bagaimana monad bekerja atau bagaimana beberapa kombinator beroperasi tanpa sistem tipe. Pertimbangkan berapa banyak tutorial tentang Haskell yang pertama kali meminta Anda mempertimbangkan jenis fungsi yang dimaksud dengan: t di REPL. Itu tidak tersedia bagi Anda dalam bahasa yang diketik secara dinamis. Tentu, semua kompleksitas dari sistem tipe masih ada. Monad masih monad. Tetapi bahasa tersebut telah memutuskan untuk mencuci tangannya dari masalah ini dan tidak memberikan bantuan sama sekali. Anda sendirian, sobat. Saya tidak mengetuk bahasa yang diketik secara dinamis. Saya sangat mencintai mereka. Skema adalah alat par excellance yang sangat baik. Tetapi Anda akan melihat bahwa ketika kita berbicara tentang hal-hal seperti monad dalam bahasa yang dinamis, kita sering menemukan notasiuntuk menggambarkan jenis prosedur. Seorang programmer fungsional akan bertempur dengan tipe satu atau lain cara. Pemeriksa tipe Haskell hanya memberi Anda alat yang bagus untuk belajar bagaimana melakukan itu.

Ara Vartanian
sumber