Getters dan Setter dalam Bahasa Fungsional

9

Salah satu prinsip Pemrograman Fungsional adalah penggunaan Fungsi Murni. Fungsi Murni adalah fungsi yang bebas efek samping dan transparan referensial.

Getters tidak transparan secara referensi - jika seorang Setter dipanggil di antara panggilan ke Getter, nilai pengembalian Getter berubah meskipun parameternya tidak (biasanya tidak ada parameter)

Setter menghasilkan efek samping - Memanggil Setter sebuah biasanya memanipulasi nilai yang tidak nilai kembali (pada kenyataannya, secara tradisional setter kembali apa-apa)

Saya tahu di Scala kita hanya menerima kenyataan bahwa kita menyatukan dua paradigma (fungsional dan berorientasi objek) dan menggunakan getter / setter seperti yang kita lakukan dalam bahasa seperti Java.

Dalam bahasa seperti Haskell (yang saya tidak fasih, tapi saya diberitahu memegang lebih benar untuk bahasa fungsional "Murni") Saya hanya ingin tahu, bagaimana Anda akan memodelkan properti pada objek sedemikian sehingga Getters secara referensial transparan dan Setter apakah efek sampingnya gratis?

Apakah solusinya dengan mengembalikan salinan objek yang ditetapkan oleh setter sebagai nilai pengembalian setter, dan salinan ini berisi perubahan ke nilai properti?

Terima kasih
sumber
8
Getters dan setter memiliki objek sebagai parameter - meskipun biasanya implisit - sehingga getter secara referensi transparan.
@delnan, hanya jika atribut yang dibacanya tidak berubah.
dan_waterworth
3
@dan_waterworth: Hanya jika kita membaca "sama" di "referensial transparan" sebagai identitas objek. Jika faktanya atribut yang mendasari berbeda membuatnya menjadi panggilan dengan argumen yang berbeda (yang sejalan dengan sebagian besar definisi kesetaraan). Ini mengabaikan utas lainnya yang memanggil setter dan menyelesaikannya di antara panggilan ke rajin dan rajin rajin, tetapi dalam kasus itu Anda tetap memiliki masalah yang lebih serius.

Jawaban:

7

Persis. Lihat metode kelas kasus copy, atau konsep umum lensa.

Secara khusus, jika keadaan perlu diubah, Anda akan menggunakan monad negara. Perubahan pada state monad dapat dilakukan melalui lensa, yang membuat penggalian informasi dari "state" dan mengubahnya menjadi mudah.

Lihat juga pertanyaan ini tentang masalah umum yang berasal dari struktur yang dalam seperti "keadaan" dan membuat perubahan padanya. Jawabannya memiliki tautan yang baik pada lensa dan resleting jika Anda ingin mengetahui lebih dalam.

Daniel C. Sobral
sumber
Pertanyaan Daniel: adakah alasan khusus bahwa salinan () terkait dengan kelas-kelas Kasus? Ini tampaknya tidak spesifik untuk kebutuhan (kata yang salah, tetapi tidak dapat memikirkan yang lain) dari kelas Case secara khusus, tampaknya (bagi saya) lebih merupakan fitur yang cocok untuk semua kelas. Bagaimana jika saya perlu menyalin () di kelas non-kasus saya? Apakah ada sifat yang dapat saya gunakan untuk mendapatkan fungsionalitas itu?
ThaDon
1
@ThaDon kelas kasus seharusnya ditentukan oleh parameter konstruktor mereka - kesetaraan, kode hash dan ekstraktor didasarkan pada asumsi ini, dan begitu juga metode salin. Pada kelas non-kasus, semua orang dapat menebak apakah semua parameter konstruktor yang diperlukan untuk menyalin kelas. Namun, Anda dapat dengan mudah menulis metode salin Anda sendiri.
Daniel C. Sobral
11

Nah, di Haskell, objek (biasanya) tidak berubah, jadi getter (yang Anda dapatkan ketika Anda menggunakan sintaks rekaman) atau fungsi yang bertindak seperti getter secara transparan transparan. Dan kemudian Anda tidak "mengatur" nilai pada objek - jika Anda membuat objek baru yang mirip dengan yang lama, tetapi dengan nilai yang berbeda untuk salah satu bidang. Ini juga merupakan fungsi murni.

MatrixFrog
sumber
1
"benda-benda (biasanya) tidak berubah" kapan bukan?
sara
-1

"Getters dan setter memiliki objek sebagai parameter - meskipun biasanya implisit - sehingga getter secara referensi transparan. - delnan"

Transparan secara referensial berarti bahwa fungsi SELALU mengembalikan output yang sama untuk input yang sama; jadi jika atribut objek telah diubah oleh setter, Anda tidak mengembalikan output yang sama. :)

Casey Hawthorne
sumber
Tetapi, jika objek diubah oleh setter, input ke pengambil (yaitu argumen diri implisit) TELAH berubah.
Stephen C. Steel
1
Nilai / pointer referensi objek tidak berubah kecuali objek telah dipindahkan di heap.
Casey Hawthorne
5
Ya, tetapi secara logis, input implisit adalah objek itu sendiri, bukan nilai pointer.
Stephen C. Steel
"jika atribut objek telah diubah oleh setter, Anda tidak mengembalikan output yang sama": Dalam istilah fungsional, Anda telah menghancurkan objek pertama dan membuat yang baru. Untuk alasan kinerja (hindari menyalin dan memperbarui referensi dari yang lama ke objek baru) Anda menyimpan objek baru di area memori yang sama yang berisi objek lama.
Giorgio