Desain skala besar di Haskell? [Tutup]

565

Apa cara yang baik untuk merancang / menyusun program fungsional besar, terutama di Haskell?

Saya telah melalui banyak tutorial (Write Yourself a Scheme menjadi favorit saya, dengan Real World Haskell dekat kedua) - tetapi sebagian besar program relatif kecil, dan tujuan tunggal. Selain itu, saya tidak menganggap beberapa dari mereka sangat elegan (misalnya, tabel pencarian luas di WYAS).

Saya sekarang ingin menulis program yang lebih besar, dengan lebih banyak bagian yang bergerak - memperoleh data dari berbagai sumber yang berbeda, membersihkannya, memprosesnya dengan berbagai cara, menampilkannya dalam antarmuka pengguna, bertahan, berkomunikasi melalui jaringan, dll. Bagaimana mungkin satu struktur kode terbaik agar dapat dibaca, dipelihara, dan mudah beradaptasi dengan perubahan persyaratan?

Ada cukup banyak literatur yang membahas pertanyaan-pertanyaan ini untuk program imperatif berorientasi objek besar. Ide-ide seperti MVC, pola desain, dll. Adalah resep yang layak untuk mewujudkan tujuan luas seperti pemisahan masalah dan penggunaan kembali dalam gaya OO. Selain itu, bahasa imperatif yang lebih baru memberikan gaya refactoring 'desain saat Anda tumbuh' yang, menurut pendapat pemula saya, Haskell tampaknya kurang cocok.

Apakah ada literatur yang setara untuk Haskell? Bagaimana kebun binatang struktur kontrol eksotis tersedia dalam pemrograman fungsional (monad, panah, aplikatif, dll.) Paling baik digunakan untuk tujuan ini? Praktik terbaik apa yang bisa Anda rekomendasikan?

Terima kasih!

EDIT (ini merupakan tindak lanjut dari jawaban Don Stewart):

@dons disebutkan: "Monads menangkap desain arsitektur utama dalam beberapa tipe."

Saya kira pertanyaan saya adalah: bagaimana seharusnya orang berpikir tentang desain arsitektur utama dalam bahasa fungsional murni?

Pertimbangkan contoh beberapa aliran data, dan beberapa langkah pemrosesan. Saya bisa menulis parser modular untuk aliran data ke sekumpulan struktur data, dan saya bisa menerapkan setiap langkah pemrosesan sebagai fungsi murni. Langkah-langkah pemrosesan yang diperlukan untuk satu bagian data akan tergantung pada nilainya dan yang lainnya. Beberapa langkah harus diikuti oleh efek samping seperti pembaruan GUI atau permintaan basis data.

Apa cara 'Benar' untuk mengikat data dan langkah-langkah parsing dengan cara yang baik? Orang bisa menulis fungsi besar yang melakukan hal yang benar untuk berbagai tipe data. Atau seseorang dapat menggunakan monad untuk melacak apa yang telah diproses sejauh ini dan meminta setiap langkah pemrosesan mendapatkan apa pun yang dibutuhkan berikutnya dari keadaan monad. Atau orang dapat menulis sebagian besar program terpisah dan mengirim pesan (saya tidak suka opsi ini).

Slide yang ditautkannya memiliki peluru Hal yang Kita Butuhkan: "Idiom untuk memetakan desain ke tipe / fungsi / kelas / monad". Apa idiomnya? :)

Dan
sumber
9
Saya pikir ide inti ketika menulis program besar dalam bahasa fungsional adalah modul kecil, khusus, dan stateless berkomunikasi melalui pesan yang lewat . Tentu saja Anda harus berpura-pura sedikit karena program yang benar membutuhkan keadaan. Saya pikir ini adalah di mana F # bersinar di atas Haskell.
ChaosPandion
18
@Chaos tetapi hanya Haskell yang menerapkan kewarganegaraan secara default. Anda tidak punya pilihan, dan harus bekerja keras untuk memperkenalkan negara (untuk memecah komposisionalitas) di Haskell :-)
Don Stewart
7
@ChaosPandion: Saya tidak setuju, secara teori. Tentu saja, dalam bahasa imperatif (atau bahasa fungsional yang dirancang untuk menyampaikan pesan), mungkin itulah yang akan saya lakukan. Tetapi Haskell memiliki cara lain untuk berurusan dengan negara, dan mungkin mereka membiarkan saya menyimpan lebih banyak manfaat 'murni'.
Dan
1
Saya menulis sedikit tentang ini di bawah "Pedoman Desain" dalam dokumen ini: community.haskell.org/~ndm/downloads/…
Neil Mitchell
5
@JonHarrop jangan lupa bahwa sementara MLOC adalah metrik yang baik ketika Anda membandingkan proyek dalam bahasa yang serupa, itu tidak masuk akal untuk perbandingan lintas-bahasa, terutama dengan bahasa seperti Haskell, di mana penggunaan kembali dan modularitas kode jauh lebih mudah & aman dibandingkan dengan beberapa bahasa di luar sana.
Tair

Jawaban:

519

Saya berbicara sedikit tentang ini dalam Proyek Besar Rekayasa di Haskell dan dalam Desain dan Implementasi XMonad. Rekayasa dalam skala besar adalah tentang mengelola kompleksitas. Mekanisme penataan kode utama di Haskell untuk mengelola kompleksitas adalah:

Sistem tipe

  • Gunakan sistem tipe untuk menegakkan abstraksi, menyederhanakan interaksi.
  • Menegakkan invarian kunci melalui tipe
    • (mis. bahwa nilai-nilai tertentu tidak dapat lepas dari beberapa cakupan)
    • Kode tertentu itu tidak memiliki IO, tidak menyentuh disk
  • Menegakkan keamanan: pengecualian yang dicek (Mungkin / Baik), hindari konsep campuran (Word, Int, Alamat)
  • Struktur data yang baik (seperti ritsleting) dapat membuat beberapa kelas pengujian tidak perlu, karena mereka mengesampingkan misalnya kesalahan di luar batas statis.

Profiler

  • Berikan bukti objektif tentang profil timbunan dan waktu program Anda.
  • Heap profiling, khususnya, adalah cara terbaik untuk memastikan tidak ada penggunaan memori yang tidak perlu.

Kemurnian

  • Kurangi kompleksitas secara dramatis dengan menghilangkan status. Skala kode murni fungsional, karena komposisional. Yang Anda butuhkan adalah tipe untuk menentukan cara menggunakan beberapa kode - kode tidak akan pecah secara misterius ketika Anda mengubah bagian lain dari program.
  • Gunakan banyak pemrograman gaya "model / view / controller": parsing data eksternal sesegera mungkin ke dalam struktur data yang benar-benar fungsional, operasikan pada struktur-struktur itu, lalu setelah semua pekerjaan selesai, render / flush / serialkan keluar. Menjaga sebagian besar kode Anda murni

Pengujian

  • QuickCheck + Cakupan Kode Haskell, untuk memastikan Anda menguji hal-hal yang tidak dapat Anda periksa dengan jenisnya.
  • GHC + RTS sangat bagus untuk melihat apakah Anda menghabiskan terlalu banyak waktu untuk melakukan GC.
  • QuickCheck juga dapat membantu Anda mengidentifikasi API ortogonal yang bersih untuk modul Anda. Jika properti kode Anda sulit untuk dinyatakan, mereka mungkin terlalu kompleks. Terus refactoring sampai Anda memiliki set properti yang bersih yang dapat menguji kode Anda, yang menyusun dengan baik. Kemudian kode tersebut mungkin dirancang dengan baik juga.

Monad untuk Penataan

  • Monads menangkap desain arsitektur utama dalam tipe (kode ini mengakses perangkat keras, kode ini adalah sesi satu pengguna, dll.)
  • Misalnya X monad di xmonad, menangkap dengan tepat desain untuk kondisi apa yang terlihat oleh komponen sistem apa.

Ketikkan kelas dan tipe eksistensial

  • Gunakan kelas tipe untuk memberikan abstraksi: sembunyikan implementasi di belakang antarmuka polimorfik.

Konkurensi dan paralelisme

  • Masuklah parke program Anda untuk mengalahkan pesaing dengan paralelisme yang mudah dan dapat dikompilasi.

Refactor

  • Anda dapat refactor di Haskell banyak . Jenis memastikan perubahan skala besar Anda akan aman, jika Anda menggunakan jenis dengan bijak. Ini akan membantu skala basis kode Anda. Pastikan refactoring Anda akan menyebabkan kesalahan ketik hingga selesai.

Gunakan FFI dengan bijak

  • FFI membuatnya lebih mudah untuk bermain dengan kode asing, tetapi kode asing itu bisa berbahaya.
  • Berhati-hatilah dalam asumsi tentang bentuk data yang dikembalikan.

Pemrograman meta

  • Sedikit Haskell Templat atau obat generik dapat menghapus boilerplate.

Pengemasan dan distribusi

  • Gunakan Cabal. Jangan gulung sistem build Anda sendiri. (EDIT: Sebenarnya Anda mungkin ingin menggunakan Stack sekarang untuk memulai.).
  • Gunakan Haddock untuk dokumentasi API yang baik
  • Alat seperti graphmod dapat menunjukkan struktur modul Anda.
  • Andalkan versi Haskell Platform dari perpustakaan dan alat, jika memungkinkan. Ini adalah basis yang stabil. (EDIT: Lagi-lagi, hari ini Anda mungkin ingin menggunakan Stack untuk mendapatkan basis yang stabil dan berjalan.)

Peringatan

  • Gunakan -Walluntuk menjaga kode Anda bersih dari bau. Anda mungkin juga melihat Agda, Isabelle atau Catch untuk jaminan lebih. Untuk serat seperti pengecekan, melihat besar hlint , yang akan menyarankan perbaikan.

Dengan semua alat ini, Anda dapat menangani kompleksitas, menghilangkan sebanyak mungkin interaksi antar komponen. Idealnya, Anda memiliki basis kode murni yang sangat besar, yang sangat mudah dipelihara, karena bersifat komposisional. Itu tidak selalu mungkin, tetapi patut bertujuan.

Secara umum: dekomposisikan unit logis sistem Anda ke dalam komponen transparan referensial terkecil yang mungkin, kemudian implementasikan dalam modul. Lingkungan global atau lokal untuk set komponen (atau komponen di dalam) mungkin dipetakan ke monads. Gunakan tipe data aljabar untuk menggambarkan struktur data inti. Bagikan definisi tersebut secara luas.

Don Stewart
sumber
8
Terima kasih Don, jawaban Anda sangat bagus - ini semua adalah pedoman yang berharga dan saya akan merujuknya secara teratur. Saya kira pertanyaan saya terjadi selangkah sebelum orang membutuhkan semua ini. Apa yang benar-benar ingin saya ketahui adalah "Idiom untuk memetakan desain ke tipe / fungsi / kelas / monad" ... Saya bisa mencoba untuk membuat sendiri, tapi saya berharap mungkin ada serangkaian praktik terbaik yang didistilasi di suatu tempat - atau jika tidak, rekomendasi untuk kode yang terstruktur dengan baik untuk membaca sistem ish besar (berbeda dengan, katakanlah, perpustakaan yang terfokus). Saya mengedit posting saya untuk mengajukan pertanyaan yang sama ini secara lebih langsung.
Dan
6
Saya telah menambahkan beberapa teks tentang dekomposisi desain ke modul. Tujuan Anda adalah untuk mengidentifikasi fungsi-fungsi yang terkait secara logis ke dalam modul-modul yang memiliki antarmuka transparan referensial dengan bagian lain dari sistem, dan untuk menggunakan tipe data yang murni fungsional sesegera mungkin, sebanyak mungkin, untuk memodelkan dunia luar dengan aman. Dokumen desain xmonad mencakup banyak hal ini: xmonad.wordpress.com/2009/09/09/…
Don Stewart
3
Saya mencoba mengunduh slide dari Proyek Besar Rekayasa dalam pembicaraan Haskell , tetapi tautannya tampaknya rusak. Ini yang berfungsi: galois.com/~dons/talks/dons-londonhug-decade.pdf
mik01aj
3
Saya berhasil menemukan tautan unduhan baru ini: pau-za.cz/data/2/sprava.pdf
Riccardo T.
3
@Heather Meskipun tautan unduhan di halaman yang saya sebutkan di komentar tepat sebelum tidak berfungsi, sepertinya slide masih dapat dilihat di scribd
Riccardo T.
118

Don memberimu sebagian besar perincian di atas, tetapi inilah dua sen saya dari melakukan program stateful yang sangat rumit seperti daemon sistem di Haskell.

  1. Pada akhirnya, Anda tinggal di tumpukan transformator monad. Di bagian bawah adalah IO. Di atas itu, setiap modul utama (dalam arti abstrak, bukan modul-in-a-file) memetakan keadaan yang diperlukan ke dalam lapisan dalam tumpukan itu. Jadi, jika Anda memiliki kode koneksi basis data yang disembunyikan dalam sebuah modul, Anda menulis semuanya menjadi lebih dari satu jenis Koneksi MonadReader m => ... -> m ... dan kemudian fungsi basis data Anda selalu dapat mendapatkan koneksi mereka tanpa fungsi dari yang lain modul harus menyadari keberadaannya. Anda mungkin berakhir dengan satu lapisan yang membawa koneksi database Anda, yang lain konfigurasi Anda, sepertiga berbagai semaphores dan mvars Anda untuk resolusi paralelisme dan sinkronisasi, yang lain menangani file log Anda, dll.

  2. Cari tahu penanganan kesalahan Anda terlebih dahulu . Kelemahan terbesar saat ini untuk Haskell dalam sistem yang lebih besar adalah kebanyakan metode penanganan kesalahan, termasuk yang buruk seperti Maybe (yang salah karena Anda tidak dapat mengembalikan informasi apa pun yang salah; selalu gunakan Yang Baik alih-alih Mungkin kecuali jika Anda benar-benar hanya berarti nilai yang hilang). Cari tahu bagaimana Anda akan melakukannya terlebih dahulu, dan atur adapter dari berbagai mekanisme penanganan kesalahan yang digunakan perpustakaan Anda dan kode lainnya menjadi yang terakhir. Ini akan menyelamatkan Anda dari dunia kesedihan nanti.

Tambahan (diekstrak dari komentar; terima kasih kepada Lii & liminalisht ) -
diskusi lebih lanjut tentang berbagai cara untuk mengiris program besar menjadi monad dalam tumpukan:

Ben Kolera memberikan pengantar praktis yang bagus untuk topik ini, dan Brian Hurt membahas solusi untuk masalah liftmemasukkan tindakan monadik ke dalam monad khusus Anda. George Wilson menunjukkan cara menggunakan mtluntuk menulis kode yang bekerja dengan monad apa pun yang mengimplementasikan jenis kacamata yang diperlukan, alih-alih jenis monad khusus Anda. Carlo Hamalainen telah menulis beberapa catatan singkat dan berguna yang merangkum pembicaraan George.

pengguna349653
sumber
5
Dua poin bagus! Jawaban ini pantas menjadi konkret, sesuatu yang tidak dimiliki orang lain. Akan menarik untuk membaca lebih banyak diskusi tentang berbagai cara untuk mengiris program besar menjadi monad dalam tumpukan. Silakan kirim tautan ke artikel tersebut jika Anda punya!
Lii
6
@Lii Ben Kolera memberikan pengantar praktis yang bagus untuk topik ini, dan Brian Hurt membahas solusi untuk masalah liftmemasukkan tindakan monadik ke dalam monad khusus Anda. George Wilson menunjukkan cara menggunakan mtluntuk menulis kode yang bekerja dengan monad apa pun yang mengimplementasikan jenis kacamata yang diperlukan, alih-alih jenis monad khusus Anda. Carlo Hamalainen telah menulis beberapa catatan singkat dan berguna yang merangkum pembicaraan George.
liminalisht
Saya setuju bahwa tumpukan transformator monad cenderung menjadi fondasi arsitektur utama, tetapi saya berusaha sangat keras untuk menjauhkan IO dari mereka. Ini tidak selalu mungkin, tetapi jika Anda berpikir tentang apa artinya "dan kemudian" dalam monad Anda, Anda mungkin menemukan bahwa Anda benar-benar memiliki kelanjutan atau otomat di suatu tempat di bagian bawah yang kemudian dapat ditafsirkan menjadi IO dengan fungsi "run".
Paul Johnson
Seperti yang telah ditunjukkan oleh @PaulJohnson, pendekatan Monad Transformer Stack ini tampaknya bertentangan dengan Pola Desain ReaderT
McBear Holden
43

Merancang program besar di Haskell tidak jauh berbeda dengan melakukannya dalam bahasa lain. Memprogram secara besar-besaran adalah tentang memecah masalah Anda menjadi bagian-bagian yang dapat dikelola, dan bagaimana menyatukannya; bahasa implementasi kurang penting.

Yang mengatakan, dalam desain besar itu bagus untuk mencoba dan memanfaatkan sistem tipe untuk memastikan Anda hanya bisa menyatukan potongan Anda dengan cara yang benar. Ini mungkin melibatkan tipe baru atau tipe hantu untuk membuat hal-hal yang tampaknya memiliki tipe yang sama menjadi berbeda.

Ketika datang ke refactoring kode saat Anda pergi, kemurnian adalah keuntungan besar, jadi cobalah untuk menjaga sebanyak mungkin dari kode murni. Kode murni mudah diperbaiki, karena tidak memiliki interaksi tersembunyi dengan bagian lain dari program Anda.

agustus
sumber
14
Saya sebenarnya menemukan bahwa refactoring cukup membuat frustrasi, jika tipe data perlu diubah. Ini membutuhkan memodifikasi banyak dari konstruktor dan pencocokan pola dengan sangat teliti. (Saya setuju bahwa refactoring fungsi murni menjadi fungsi murni lainnya dari jenis yang sama itu mudah - selama seseorang tidak menyentuh tipe data)
Dan
2
@Dan Anda bisa keluar sepenuhnya gratis dengan perubahan yang lebih kecil (seperti hanya menambahkan bidang) saat Anda menggunakan catatan. Beberapa orang mungkin ingin membuat catatan sebagai kebiasaan (saya salah satunya ^^ ").
MasterMastic
5
@Apakah maksud saya jika Anda mengubah tipe data suatu fungsi dalam bahasa apa pun, tidakkah Anda harus melakukan hal yang sama? Saya tidak melihat bagaimana bahasa seperti Java atau C ++ akan membantu Anda dalam hal ini. Jika Anda mengatakan bahwa Anda dapat menggunakan semacam antarmuka umum yang kedua jenis patuhi maka Anda seharusnya telah melakukannya dengan Typeclasses di Haskell.
titik koma
4
@semicon perbedaan untuk bahasa seperti Java adalah keberadaan alat yang matang, teruji dengan baik dan sepenuhnya otomatis untuk refactoring. Secara umum alat-alat ini memiliki integrasi editor yang luar biasa, dan menghilangkan banyak pekerjaan yang membosankan terkait dengan refactoring. Haskell memberi kita sistem tipe brilian untuk mendeteksi hal-hal yang harus diubah dalam suatu refactoring, tetapi alat untuk benar-benar melakukan refactoring itu (saat ini) sangat terbatas, terutama dibandingkan dengan apa yang telah tersedia di Jawa ekosistem selama lebih dari 10 tahun.
jsk
16

Saya belajar pemrograman fungsional terstruktur pertama kali dengan buku ini . Ini mungkin bukan apa yang Anda cari, tetapi untuk pemula dalam pemrograman fungsional, ini mungkin salah satu langkah pertama yang terbaik untuk belajar menyusun program fungsional - independen dari skala. Pada semua level abstraksi, desain harus selalu memiliki struktur yang diatur dengan jelas.

Kerajinan Pemrograman Fungsional

Kerajinan Pemrograman Fungsional

http://www.cs.kent.ac.uk/people/staff/sjt/craft2e/

comonad
sumber
11
Sebesar Kerajinan FP - saya belajar Haskell dari itu - itu adalah teks pengantar untuk programmer pemula , bukan untuk desain sistem besar di Haskell.
Don Stewart
3
Ya, Ini adalah buku terbaik yang saya tahu tentang merancang API dan menyembunyikan detail implementasi. Dengan buku ini, saya menjadi programmer yang lebih baik dalam C ++ - hanya karena saya belajar cara yang lebih baik untuk mengatur kode saya. Yah, pengalaman Anda (dan jawaban) jelas lebih baik dari buku ini, tetapi Dan mungkin masih pemula di Haskell. ( where beginner=do write $ tutorials `about` Monads)
comonad
11

Saat ini saya sedang menulis buku dengan judul "Desain Fungsional dan Arsitektur". Ini memberi Anda satu set lengkap teknik bagaimana membangun aplikasi besar menggunakan pendekatan fungsional murni. Ini menjelaskan banyak pola dan ide fungsional sambil membangun aplikasi 'Andromeda' seperti SCADA untuk mengendalikan pesawat ruang angkasa dari awal. Bahasa utama saya adalah Haskell. Buku ini mencakup:

  • Pendekatan pemodelan arsitektur menggunakan diagram;
  • Analisa Kebutuhan;
  • Pemodelan domain DSL tertanam;
  • Desain dan implementasi DSL eksternal;
  • Monads sebagai subsistem dengan efek;
  • Monad gratis sebagai antarmuka fungsional;
  • EDSL yang terindah;
  • Inversi Kontrol menggunakan eDSLs monadik Gratis;
  • Memori Transaksional Perangkat Lunak;
  • Lensa;
  • Negara, Pembaca, Penulis, RWS, ST monads;
  • Status tidak murni: IORef, MVar, STM;
  • Multithreading dan pemodelan domain bersamaan;
  • GUI;
  • Penerapan teknik dan pendekatan arus utama seperti UML, SOLID, GRASP;
  • Interaksi dengan subsistem yang tidak murni.

Anda mungkin mengenal kode untuk buku di sini , dan kode proyek 'Andromeda' .

Saya berharap untuk menyelesaikan buku ini pada akhir 2017. Sampai itu terjadi, Anda dapat membaca artikel saya "Desain dan Arsitektur dalam Pemrograman Fungsional" (Rus) di sini .

MEMPERBARUI

Saya membagikan buku saya secara online (5 bab pertama). Lihat posting di Reddit

granina
sumber
Alexander, bisakah Anda memperbarui catatan ini ketika buku Anda selesai, jadi kami bisa mengikutinya. Bersulang.
Maks
4
Tentu! Untuk saat ini saya menyelesaikan setengah dari teks, tapi ini 1/3 dari keseluruhan pekerjaan. Jadi, jaga minat Anda, ini sangat menginspirasi saya!
granina
2
Hai! Saya membagikan buku saya secara online (hanya 5 bab pertama). Lihat posting di Reddit: reddit.com/r/haskell/comments/6ck72h/…
graninas
terima kasih sudah berbagi dan bekerja!
Maks
Sangat menantikan ini!
patriques
7

Posting blog Gabriel Arsitektur program yang dapat diskala mungkin perlu disebutkan.

Pola desain Haskell berbeda dari pola desain utama dalam satu cara penting:

  • Arsitektur konvensional : Gabungkan beberapa komponen bersama tipe A untuk menghasilkan "jaringan" atau "topologi" tipe B

  • Arsitektur Haskell : Gabungkan beberapa komponen bersama-sama dari tipe A untuk menghasilkan komponen baru dari tipe A yang sama, karakternya tidak dapat dibedakan dari bagian substituennya

Saya sering kaget bahwa arsitektur yang tampak elegan sering cenderung keluar dari perpustakaan yang menunjukkan rasa homogenitas yang bagus, dengan cara bottom-up. Dalam Haskell ini sangat jelas - pola yang secara tradisional akan dianggap "arsitektur top-down" cenderung ditangkap di perpustakaan seperti mvc , Netwire dan Cloud Haskell . Artinya, saya harap jawaban ini tidak akan diartikan sebagai upaya menggantikan yang lain di utas ini, hanya saja pilihan struktural dapat dan idealnya disarikan di perpustakaan oleh para pakar domain. Kesulitan nyata dalam membangun sistem besar, menurut pendapat saya, adalah mengevaluasi perpustakaan-perpustakaan ini berdasarkan "kebaikan" arsitekturalnya versus semua masalah pragmatis Anda.

Seperti yang disebutkan oleh liminalisht dalam komentar, Pola desain kategori adalah posting lain oleh Gabriel pada topik, dalam nada yang sama.

Rehno Lindeque
sumber
3
Saya akan menyebutkan posting lain oleh Gabriel Gonzalez pada pola desain kategori . Argumen dasarnya adalah bahwa apa yang oleh para programmer fungsional kita anggap sebagai "arsitektur yang baik" benar-benar "arsitektur komposisi" - itu merancang program menggunakan item yang dijamin untuk dikomposisi. Karena undang-undang kategori menjamin bahwa identitas dan asosiatif dipertahankan di bawah komposisi, arsitektur komposisi dicapai dengan menggunakan abstraksi yang kami miliki kategorinya - misalnya fungsi murni, tindakan monadik, pipa, dll.
liminalisht
3

Mungkin Anda harus melangkah mundur dan memikirkan bagaimana menerjemahkan deskripsi masalah ke desain. Karena Haskell sangat tinggi, ia dapat menangkap deskripsi masalah dalam bentuk struktur data, tindakan sebagai prosedur, dan transformasi murni sebagai fungsi. Maka Anda memiliki desain. Pengembangan dimulai ketika Anda mengkompilasi kode ini dan menemukan kesalahan konkret tentang bidang yang hilang, instance yang hilang, dan transformator monadik yang hilang dalam kode Anda, karena misalnya Anda melakukan akses database dari perpustakaan yang memerlukan monad keadaan tertentu dalam prosedur IO. Dan voila, ada programnya. Kompiler memberi makan sketsa mental Anda dan memberikan koherensi pada desain dan pengembangannya.

Sedemikian rupa Anda mendapat manfaat dari bantuan Haskell sejak awal, dan pengkodean adalah alami. Saya tidak akan peduli untuk melakukan sesuatu yang "fungsional" atau "murni" atau cukup umum jika apa yang ada dalam pikiran Anda adalah masalah biasa yang konkret. Saya pikir over-engineering adalah hal paling berbahaya di TI. Hal-hal berbeda ketika masalahnya adalah membuat perpustakaan yang abstrak satu set masalah terkait.

agocorona
sumber