Saya baru-baru ini menangkap bug FP (mencoba mempelajari Haskell), dan saya benar-benar terkesan dengan apa yang saya lihat sejauh ini (fungsi kelas satu, evaluasi malas, dan semua barang lainnya). Saya belum ahli, tapi saya sudah mulai merasa lebih mudah untuk alasan "fungsional" daripada keharusan untuk algoritma dasar (dan saya mengalami kesulitan untuk kembali ke tempat saya harus).
Satu-satunya area di mana FP saat ini tampaknya gagal, adalah pemrograman GUI. Pendekatan Haskell tampaknya hanya membungkus toolkit GUI imperatif (seperti GTK + atau wxWidgets) dan menggunakan blok "do" untuk mensimulasikan gaya imperatif. Saya belum pernah menggunakan F #, tetapi pemahaman saya adalah bahwa ia melakukan sesuatu yang mirip menggunakan OOP dengan kelas .NET. Jelas, ada alasan bagus untuk ini - pemrograman GUI saat ini adalah semua tentang IO dan efek samping, jadi pemrograman murni fungsional tidak mungkin dilakukan dengan sebagian besar kerangka kerja saat ini.
Pertanyaan saya adalah, apakah mungkin untuk memiliki pendekatan fungsional untuk pemrograman GUI? Saya mengalami kesulitan membayangkan seperti apa ini dalam praktiknya. Adakah yang tahu kerangka kerja, eksperimental atau lainnya, yang mencoba hal semacam ini (atau bahkan kerangka kerja yang dirancang dari bawah ke atas untuk bahasa fungsional)? Atau solusi untuk hanya menggunakan pendekatan hybrid, dengan OOP untuk bagian-bagian GUI dan FP untuk logika? (Saya hanya bertanya karena penasaran - Saya ingin berpikir bahwa FP adalah "masa depan," tetapi pemrograman GUI sepertinya lubang yang cukup besar untuk diisi.)
Jawaban:
Itu tidak benar-benar "pendekatan Haskell" - itu hanya bagaimana Anda mengikat toolkit GUI imperatif paling langsung - melalui antarmuka imperatif. Haskell kebetulan memiliki ikatan yang cukup menonjol.
Ada beberapa pendekatan yang cukup matang, atau lebih eksperimental fungsional / deklaratif murni untuk GUI, kebanyakan di Haskell, dan terutama menggunakan pemrograman reaktif fungsional.
Beberapa contoh adalah:
Bagi Anda yang tidak terbiasa dengan Haskell, Flapjax, http://www.flapjax-lang.org/ adalah implementasi pemrograman reaktif fungsional di atas JavaScript.
sumber
Kata-kata kunci yang Anda cari adalah "pemrograman reaktif fungsional" (FRP).
Conal Elliott dan beberapa yang lain telah membuat sedikit industri rumahan karena berusaha menemukan abstraksi yang tepat untuk FRP. Ada beberapa implementasi konsep FRP di Haskell.
Anda dapat mempertimbangkan untuk memulai dengan makalah "Pemrograman Reaktif Fungsional Reaktif" terbaru dari Conal , tetapi ada beberapa implementasi (lama) lainnya, beberapa di antaranya terhubung dari situs haskell.org . Conal memiliki kemampuan untuk mencakup seluruh domain, dan makalahnya dapat dibaca tanpa mengacu pada apa yang datang sebelumnya.
Untuk mengetahui bagaimana pendekatan ini dapat digunakan untuk pengembangan GUI, Anda mungkin ingin melihat Fudgets , yang saat ini semakin lama, yang dirancang pada pertengahan 90-an, memang menghadirkan pendekatan FRP yang solid untuk desain GUI.
sumber
Windows Presentation Foundation adalah bukti bahwa pendekatan fungsional berfungsi sangat baik untuk pemrograman GUI. Ini memiliki banyak aspek fungsional dan kode WPF "baik" (mencari pola MVVM) menekankan pendekatan fungsional lebih dari keharusan. Saya berani mengklaim bahwa WPF adalah toolkit GUI fungsional dunia nyata yang paling sukses :-)
WPF menjelaskan antarmuka pengguna dalam XAML (meskipun Anda dapat menulis ulang untuk secara fungsional mencari C # atau F # juga), jadi untuk membuat beberapa antarmuka pengguna Anda akan menulis:
Selain itu, WPF juga memungkinkan Anda untuk mendeskripsikan secara animasi dan reaksi terhadap peristiwa menggunakan serangkaian tag deklaratif lain (sekali lagi, hal yang sama dapat ditulis sebagai kode C # / F #):
Sebenarnya, saya berpikir bahwa WPF memiliki banyak kesamaan dengan Haskell's FRP (meskipun saya percaya bahwa desainer WPF tidak tahu tentang FRP dan itu agak disayangkan - WPF kadang-kadang terasa agak aneh dan tidak jelas jika Anda menggunakan fungsional sudut pandang).
sumber
INotifyPropertyChanged
semua hal), tampaknya bertentangan dengan FP bagi saya. Saya jelas bukan ahli FP, dan mungkin saya terlalu fokus pada aspek immutabilitas dibandingkan dengan aspek deklaratif, tapi saya kesulitan melihat bagaimana pola MVVM (seperti yang biasanya digunakan) adalah contoh FP.INotifyPropertyChanged
hanyalah fungsi pembaruan yang Anda berikan ke mana pun Anda perlu menangani pembaruan GUI - ini adalah perbaikan latensi.Saya benar-benar akan mengatakan bahwa pemrograman fungsional (F #) adalah alat yang jauh lebih baik untuk pemrograman antarmuka pengguna daripada misalnya C #. Anda hanya perlu memikirkan masalahnya sedikit berbeda.
Saya membahas topik ini dalam buku pemrograman fungsional saya di Bab 16, tetapi ada kutipan gratis yang tersedia , yang menunjukkan (IMHO) pola paling menarik yang dapat Anda gunakan di F #. Katakanlah Anda ingin menerapkan menggambar persegi panjang (pengguna menekan tombol, menggerakkan mouse dan melepaskan tombol). Di F #, Anda dapat menulis sesuatu seperti ini:
Ini adalah pendekatan yang sangat penting (dalam gaya F # pragmatis yang biasa), tetapi ia menghindari penggunaan keadaan yang bisa berubah untuk menyimpan keadaan gambar saat ini dan untuk menyimpan lokasi inital. Meskipun dapat dibuat lebih fungsional, saya menulis perpustakaan yang melakukan itu sebagai bagian dari tesis Master saya, yang seharusnya tersedia di blog saya dalam beberapa hari ke depan.
Pemrograman Reaktif Fungsional adalah pendekatan yang lebih fungsional, tetapi saya merasa agak sulit untuk digunakan karena mengandalkan fitur Haskell yang cukup canggih (seperti panah). Namun, sangat elegan dalam banyak kasus. Keterbatasannya adalah bahwa Anda tidak dapat dengan mudah menyandikan mesin negara (yang merupakan model mental yang berguna untuk program reaktif). Ini sangat mudah menggunakan teknik F # di atas.
sumber
IObservable
.Apakah Anda menggunakan bahasa fungsional / hibrid OO seperti F # atau OCaml, atau dalam bahasa yang murni fungsional seperti Haskell di mana efek samping diturunkan ke IO monad, biasanya diperlukan satu ton pekerjaan yang diperlukan untuk mengelola GUI lebih seperti "efek samping" daripada seperti algoritma yang murni fungsional.
Yang mengatakan, telah ada beberapa penelitian yang sangat solid dimasukkan ke dalam GUI fungsional . Bahkan ada beberapa (kebanyakan) toolkit fungsional seperti Fudgets atau FranTk .
sumber
Anda bisa melihat seri oleh Don Syme di F # di mana dia melakukan demo membuat gui. tautan berikut adalah ke bagian ketiga dari seri (Anda dapat menautkan dari sana ke dua bagian lainnya).
Menggunakan F # untuk pengembangan WPF akan menjadi paradigma GUI yang sangat menarik ...
http://channel9.msdn.com/shows/Going+Deep/C9-Lectures-Dr-Don-Syme-Introduction-to-F-3-of-3/
sumber
Salah satu ide yang membuka pikiran di balik Pemrograman Fungsional Reaktif adalah memiliki fungsi penanganan peristiwa yang menghasilkan KEDUA reaksi terhadap peristiwa DAN fungsi penanganan acara berikutnya. Dengan demikian sistem yang berkembang direpresentasikan sebagai urutan fungsi penanganan acara.
Bagi saya, belajar tentang Yampa menjadi hal penting untuk mendapatkan fungsi yang menghasilkan fungsi dengan benar. Ada beberapa surat kabar bagus tentang Yampa. Saya merekomendasikan The Yampa Arcade:
http://www.cs.nott.ac.uk/~nhn/Talks/HW2003-YampaArcade.pdf (slide, PDF) http://www.cs.nott.ac.uk/~nhn/Publications/hw2003. pdf (artikel lengkap, PDF)
Ada halaman wiki di Yampa di Haskell.org
http://www.haskell.org/haskellwiki/Yampa
Halaman muka Yampa asli:
http://www.haskell.org/yampa (sayangnya saat ini rusak)
sumber
Sejak pertanyaan ini pertama kali diajukan, pemrograman reaktif fungsional telah dibuat sedikit lebih utama oleh Elm.
Saya sarankan memeriksanya di http://elm-lang.org , yang juga memiliki beberapa tutorial interaktif yang sangat bagus tentang cara membuat GUI dalam peramban yang berfungsi penuh.
Hal ini memungkinkan Anda untuk membuat GUI berfungsi penuh di mana kode yang Anda butuhkan untuk memasok sendiri hanya terdiri dari fungsi-fungsi murni. Saya pribadi merasa jauh lebih mudah untuk masuk daripada berbagai kerangka kerja GUI Haskell.
sumber
Pembicaraan Elliot tentang FRP dapat ditemukan di sini .
Selain itu, bukan benar-benar jawaban tetapi komentar dan beberapa pemikiran : entah bagaimana istilah "GUI fungsional" tampaknya sedikit seperti sebuah oxymoron (kemurnian dan IO dalam istilah yang sama).
Tetapi pemahaman saya yang kabur adalah bahwa pemrograman GUI fungsional adalah tentang mendefinisikan secara deklaratif fungsi tergantung waktu yang mengambil input pengguna (nyata) bergantung waktu dan menghasilkan output GUI yang tergantung waktu.
Dengan kata lain, fungsi ini didefinisikan seperti persamaan diferensial secara deklaratif, alih-alih oleh suatu algoritma yang secara imperatif menggunakan keadaan bisa berubah-ubah.
Jadi dalam FP konvensional seseorang menggunakan fungsi waktu independen, sedangkan di FRP orang menggunakan fungsi tergantung waktu sebagai blok bangunan untuk menggambarkan suatu program.
Mari kita berpikir tentang mensimulasikan bola pada pegas yang dengannya pengguna dapat berinteraksi. Posisi bola adalah output grafis (di layar), pengguna mendorong bola adalah penekanan tombol (input).
Mendeskripsikan program simulasi ini dalam FRP (menurut pemahaman saya) dilakukan oleh persamaan diferensial tunggal (secara deklaratif): akselerasi * massa = - rentangan pegas * konstanta pegas + Gaya yang diberikan oleh pengguna.
Berikut adalah video tentang ELM yang menggambarkan sudut pandang ini.
sumber
Pada 2016, ada beberapa kerangka kerja FRP yang relatif lebih matang untuk Haskell seperti Sodium dan Reflex (tetapi juga Netwire).
The Manning buku tentang Pemrograman Fungsional Reaktif showcase versi Java dari Sodium, untuk contoh bekerja, dan menggambarkan bagaimana sebuah FRP GUI berperilaku basis kode dan skala dibandingkan dengan imperatif serta pendekatan berbasis Aktor.
Ada juga makalah baru-baru ini tentang Arrowized FRP dan prospek menggabungkan efek samping, IO, dan mutasi dalam pengaturan FRP murni yang taat hukum: http://haskell.cs.yale.edu/wp-content/uploads/2015/10/ dwc-yale-diformat-disertasi.pdf .
Juga perlu dicatat adalah bahwa kerangka kerja JavaScript seperti ReactJS dan Angular dan banyak lainnya sudah atau sedang bergerak ke arah menggunakan FRP atau pendekatan fungsional untuk mencapai komponen GUI yang skalabel dan komposer.
sumber
Bahasa markup seperti XUL memungkinkan Anda untuk membangun GUI dengan cara deklaratif.
sumber
Untuk mengatasi ini saya memposting beberapa pemikiran saya dalam menggunakan F #,
http://fadsworld.wordpress.com/2011/04/13/f-in-the-enterprise-i/ http://fadsworld.wordpress.com/2011/04/17/fin-the-enterprise-ii- 2 /
Saya juga berencana melakukan tutorial video untuk menyelesaikan seri dan menunjukkan bagaimana F # dapat berkontribusi dalam pemrograman UX.
Saya hanya berbicara dalam konteks F # di sini.
-Fahad
sumber
Semua jawaban lain ini dibangun di atas pemrograman fungsional, tetapi membuat banyak keputusan desain sendiri. Salah satu perpustakaan yang dibangun pada dasarnya sepenuhnya dari fungsi dan tipe data abstrak sederhana adalah
gloss
. Ini adalah tipe untukplay
fungsinya dari sumberSeperti yang Anda lihat, ini berfungsi sepenuhnya dengan memasok fungsi murni dengan tipe abstrak sederhana, yang perpustakaan lain bantu.
sumber
Inovasi yang paling jelas diperhatikan oleh orang-orang yang baru mengenal Haskell adalah bahwa ada pemisahan antara dunia yang tidak murni yang berkaitan dengan komunikasi dengan dunia luar, dan dunia murni dari komputasi dan algoritma. Pertanyaan pemula yang sering muncul adalah "Bagaimana saya bisa menyingkirkan
IO
, yaitu, dikonversiIO a
menjadia
?" Cara untuk itu adalah dengan menggunakan monads (atau abstraksi lainnya) untuk menulis kode yang melakukan efek IO dan rantai. Kode ini mengumpulkan data dari dunia luar, membuat modelnya, melakukan perhitungan, mungkin dengan menggunakan kode murni, dan menampilkan hasilnya.Sejauh menyangkut model di atas, saya tidak melihat ada yang sangat salah dengan memanipulasi GUI di
IO
monad. Masalah terbesar yang muncul dari gaya ini adalah bahwa modul tidak dapat dikomposisikan lagi, yaitu, saya kehilangan sebagian besar pengetahuan saya tentang urutan eksekusi pernyataan di program saya. Untuk memulihkannya, saya harus menerapkan alasan yang sama seperti pada kode GUI imperatif. Sementara itu, untuk kode non-GUI yang tidak murni, urutan eksekusi jelas karena definisi operatorIO
monad>==
(setidaknya selama hanya ada satu utas). Untuk kode murni, tidak masalah sama sekali, kecuali dalam kasus sudut untuk meningkatkan kinerja atau untuk menghindari evaluasi yang mengakibatkan⊥
.Perbedaan filosofis terbesar antara konsol dan IO grafis adalah bahwa program yang menerapkan biasanya ditulis dalam gaya sinkron. Hal ini dimungkinkan karena ada (mengabaikan sinyal dan deskriptor file terbuka lainnya) hanya satu sumber peristiwa: aliran byte yang biasa disebut
stdin
. GUI pada dasarnya asinkron, dan harus bereaksi terhadap kejadian keyboard dan klik mouse.Filosofi populer melakukan asynchronous IO dengan cara fungsional disebut Functional Reactive Programming (FRP). Ini mendapat banyak daya tarik baru-baru ini dalam bahasa yang tidak murni, non-fungsional berkat perpustakaan seperti ReactiveX , dan kerangka kerja seperti Elm. Singkatnya, ini seperti melihat elemen GUI dan hal-hal lain (seperti file, jam, alarm, keyboard, mouse) sebagai sumber acara, yang disebut "dapat diamati", yang memancarkan aliran peristiwa. Peristiwa ini digabungkan dengan menggunakan operator akrab seperti
map
,foldl
,zip
,filter
,concat
,join
, dll, untuk menghasilkan aliran baru. Ini berguna karena status program itu sendiri dapat dilihat sebagaiscanl . map reactToEvents $ zipN <eventStreams>
program, di manaN
sama dengan jumlah yang dapat diamati yang pernah dipertimbangkan oleh program.Bekerja dengan FRP yang dapat diamati memungkinkan untuk memulihkan kompabilitas karena peristiwa dalam aliran diperintahkan dalam waktu. Alasannya adalah bahwa abstraksi aliran peristiwa memungkinkan untuk melihat semua yang dapat diamati sebagai kotak hitam. Pada akhirnya, menggabungkan aliran acara menggunakan operator memberikan kembali beberapa pemesanan lokal pada eksekusi. Ini memaksa saya untuk menjadi lebih jujur tentang invarian mana yang benar-benar diandalkan oleh program saya, mirip dengan cara semua fungsi di Haskell harus transparan transparan: jika saya ingin menarik data dari bagian lain dari program saya, saya harus eksplisit. iklan menyatakan jenis yang sesuai untuk fungsi saya. (The IO monad, menjadi bahasa Domain-Khusus untuk menulis kode tidak murni, secara efektif menghindari ini)
sumber
Pemrograman fungsional mungkin telah pindah dari ketika saya masih di universitas, tetapi seingat saya poin utama dari sistem pemrograman fungsional adalah untuk menghentikan programmer membuat "efek samping". Namun pengguna membeli perangkat lunak karena efek samping yang dibuat, misalnya memperbarui UI.
sumber