Setidaknya ada tiga perpustakaan populer untuk mengakses dan memanipulasi bidang catatan. Yang saya tahu adalah: data-accessor, fclabels dan lensa.
Secara pribadi saya mulai dengan pengakses data dan saya menggunakannya sekarang. Namun baru-baru ini di haskell-cafe ada pendapat bahwa fclabels lebih unggul.
Karena itu saya tertarik untuk membandingkan ketiga perpustakaan tersebut (dan mungkin lebih).
data-structures
haskell
record
lenses
Tener
sumber
sumber
lens
paket memiliki fungsionalitas dan dokumentasi terkaya, jadi jika Anda tidak keberatan dengan kerumitan dan ketergantungannya, itulah cara yang harus dilakukan.Jawaban:
Setidaknya ada 4 perpustakaan yang saya sadari menyediakan lensa.
Gagasan lensa adalah bahwa lensa menyediakan sesuatu yang isomorfik
menyediakan dua fungsi: pengambil dan penyetel
tunduk pada tiga undang-undang:
Pertama, bahwa jika Anda meletakkan sesuatu, Anda bisa mendapatkannya kembali
Kedua, mendapatkan dan mengatur tidak mengubah jawaban
Dan ketiga, menempatkan dua kali sama dengan menempatkan satu kali, atau lebih tepatnya, yang kedua menang.
Perhatikan, bahwa sistem tipe tidak cukup untuk memeriksa undang-undang ini untuk Anda, jadi Anda harus memastikannya sendiri tidak peduli apa pun penerapan lensa yang Anda gunakan.
Banyak perpustakaan ini juga menyediakan banyak combinator tambahan di atas, dan biasanya beberapa bentuk mesin haskell template untuk secara otomatis menghasilkan lensa untuk bidang tipe rekaman sederhana.
Dengan mengingat hal itu, kita dapat beralih ke implementasi yang berbeda:
Implementasi
fclabels
fclabels mungkin merupakan alasan paling mudah tentang perpustakaan lensa, karena itu
a :-> b
dapat langsung diterjemahkan ke jenis di atas. Ini memberikan contoh Kategori(:->)
yang berguna karena memungkinkan Anda untuk membuat lensa. Ini juga menyediakanPoint
jenis tanpa hukum yang menggeneralisasikan gagasan tentang lensa yang digunakan di sini, dan beberapa pipa ledeng untuk menangani isomorfisma.Salah satu kendala untuk adopsi
fclabels
adalah bahwa paket utama termasuk pipa templat-haskell, sehingga paket tersebut tidak Haskell 98, dan itu juga memerlukanTypeOperators
ekstensi (cukup non-kontroversial) .pengakses data
[Sunting:
data-accessor
tidak lagi menggunakan representasi ini, tetapi telah pindah ke bentuk yang mirip dengandata-lens
. Aku menyimpan komentar ini.]Data-accessor agak lebih populer daripada
fclabels
, sebagian karena merupakan Haskell 98. Namun, pilihannya dari representasi internal membuat saya muntah di mulut saya sedikit.Jenis
T
yang digunakan untuk mewakili lensa didefinisikan secara internalAkibatnya, untuk
get
nilai lensa, Anda harus mengirimkan nilai yang tidak ditentukan untuk argumen 'a'! Ini mengejutkan saya sebagai implementasi yang sangat jelek dan ad hoc.Yang mengatakan, Henning telah memasukkan pipa templat-haskell untuk secara otomatis menghasilkan pengakses untuk Anda dalam paket ' data-accessor-templat ' terpisah.
Ini memiliki manfaat dari paket besar yang sudah digunakan, yaitu Haskell 98, dan memberikan
Category
contoh yang sangat penting , jadi jika Anda tidak memperhatikan bagaimana sosis dibuat, paket ini sebenarnya pilihan yang cukup masuk akal .lensa
Selanjutnya, ada paket lensa , yang mengamati bahwa lensa dapat memberikan homomorfisma monad negara antara dua monad keadaan, dengan menetapkan lensa secara langsung sebagai homomorfisma monad tersebut.
Jika benar-benar repot untuk memberikan tipe untuk lensanya, mereka akan memiliki tipe peringkat-2 seperti:
Akibatnya, saya lebih suka tidak menyukai pendekatan ini, karena itu dengan sia-sia menarik Anda keluar dari Haskell 98 (jika Anda ingin tipe yang disediakan untuk lensa Anda secara abstrak) dan membuat Anda kehilangan
Category
instance untuk lensa, yang akan membuat Anda buat mereka dengan.
. Implementasi juga membutuhkan kelas tipe multi-parameter.Catatan, semua perpustakaan lensa lain yang disebutkan di sini menyediakan beberapa kombinator atau dapat digunakan untuk memberikan efek fokalisasi keadaan yang sama ini, jadi tidak ada yang diperoleh dengan menyandikan lensa Anda secara langsung dengan cara ini.
Selain itu, kondisi-sisi yang dinyatakan di awal tidak benar-benar memiliki ekspresi yang bagus dalam formulir ini. Seperti halnya 'fclabels', ini menyediakan metode template-haskell untuk secara otomatis menghasilkan lensa untuk jenis rekaman langsung dalam paket utama.
Karena kurangnya
Category
instans, baroque encoding, dan persyaratan template-haskell dalam paket utama, ini adalah implementasi yang paling tidak saya sukai.lensa data
[Sunting: Pada 1.8.0, ini telah berpindah dari paket comonad-transformer ke lensa-data]
data-lens
Paket saya menyediakan lensa dalam hal comonad Store .dimana
Diperluas ini setara dengan
Anda dapat melihat ini sebagai memfaktorkan argumen umum dari pengambil dan penyetel untuk mengembalikan pasangan yang terdiri dari hasil pengambilan elemen, dan penyetel untuk mengembalikan nilai baru. Ini menawarkan manfaat komputasi bahwa 'penyetel' di sini dapat mendaur ulang beberapa pekerjaan yang digunakan untuk mendapatkan nilai, membuat operasi 'modifikasi' yang lebih efisien daripada dalam
fclabels
definisi, terutama ketika accessors dirantai.Ada juga justifikasi teoretis yang bagus untuk representasi ini, karena subset dari nilai-nilai 'Lens' yang memenuhi 3 hukum yang dinyatakan di awal respons ini adalah lensa-lensa yang fungsi yang dibungkusnya adalah 'comonad coalgebra' untuk comonad store . Ini mengubah 3 hukum berbulu untuk lensa
l
menjadi 2 setara dengan pointfree:Pendekatan ini pertama kali dicatat dan dijelaskan dalam Russell O'Connor
Functor
adalah untukLens
sebagaiApplicative
adalah untukBiplate
: Memperkenalkan Multiplate dan blog tentang didasarkan pada preprint oleh Jeremy Gibbons.Ini juga mencakup sejumlah kombinator untuk bekerja dengan lensa secara ketat dan beberapa lensa stok untuk wadah, seperti
Data.Map
.Jadi lensa dalam
data-lens
bentukCategory
(tidak sepertilenses
paket), adalah Haskell 98 (tidak sepertifclabels
/lenses
), waras (tidak seperti bagian belakangdata-accessor
) dan memberikan implementasi yang sedikit lebih efisien,data-lens-fd
menyediakan fungsionalitas untuk bekerja dengan MonadState bagi mereka yang mau melangkah keluar dari Haskell 98, dan mesin templat-haskell sekarang tersedia melaluidata-lens-template
.Pembaruan 6/28/2012: Strategi Implementasi Lensa Lainnya
Lensa Isomorfisme
Ada dua pengkodean lensa lain yang patut dipertimbangkan. Yang pertama memberikan cara teoretis yang bagus untuk melihat lensa sebagai cara untuk memecah struktur menjadi nilai bidang, dan 'segalanya'.
Diberi jenis untuk isomorfisma
sedemikian rupa sehingga anggota yang sah memenuhi
hither . yon = id
, danyon . hither = id
Kami dapat mewakili lensa dengan:
Ini terutama berguna sebagai cara untuk memikirkan arti lensa, dan kita dapat menggunakannya sebagai alat penalaran untuk menjelaskan lensa lain.
Lensa van Laarhoven
Kita dapat memodelkan lensa sedemikian rupa sehingga dapat dikomposisi dengan
(.)
danid
, bahkan tanpa menggunakanCategory
instancesebagai jenis untuk lensa kami.
Maka mendefinisikan lensa semudah:
dan Anda dapat memvalidasi sendiri bahwa komposisi fungsi adalah komposisi lensa.
Saya baru-baru ini menulis tentang bagaimana Anda bisa lebih jauh menggeneralisasikan lensa van Laarhoven untuk mendapatkan keluarga lensa yang dapat mengubah jenis bidang, hanya dengan menggeneralisasi tanda tangan ini ke
Ini memang memiliki konsekuensi yang disayangkan bahwa cara terbaik untuk berbicara tentang lensa adalah dengan menggunakan polimorfisme peringkat 2, tetapi Anda tidak perlu menggunakan tanda tangan itu secara langsung ketika menentukan lensa.
The
Lens
I yang didefinisikan di atas untuk_2
sebenarnya adalahLensFamily
.Saya telah menulis perpustakaan yang mencakup lensa, keluarga lensa, dan generalisasi lainnya termasuk getter, setter, lipatan dan traversal. Ini tersedia di hackage sebagai
lens
paket.Sekali lagi, keuntungan besar dari pendekatan ini adalah bahwa pengelola perpustakaan dapat benar-benar membuat lensa dengan gaya ini di perpustakaan Anda tanpa menimbulkan ketergantungan perpustakaan lensa apa pun, hanya dengan memasok fungsi dengan tipe
Functor f => (b -> f b) -> a -> f a
, untuk tipe khusus mereka 'a' dan 'b'. Ini sangat menurunkan biaya adopsi.Karena Anda tidak perlu benar-benar menggunakan paket untuk menentukan lensa baru, dibutuhkan banyak tekanan dari kekhawatiran saya sebelumnya tentang menjaga perpustakaan Haskell 98.
sumber
:->
data-accessor
, dan kemudian saya menyerahkannya kepada Henning dan berhenti memperhatikan. Thea -> r -> (a,r)
representasi juga membuat saya tidak nyaman, dan implementasi asli saya adalah seperti AndaLens
jenis. Heeennnninngg !!