The Applicativetypeclass mewakili longgar monoidal functors yang melestarikan struktur monoidal Cartesian pada kategori fungsi diketik.
Dengan kata lain, diberikan kesaksian isomorfisme kanonik yang (,)membentuk struktur monoid:
-- Implementations left to the motivated reader
assoc_fwd :: ((a, b), c) -> (a, (b, c))
assoc_bwd :: (a, (b, c)) -> ((a, b), c)
lunit_fwd :: ((), a) -> a
lunit_bwd :: a -> ((), a)
runit_fwd :: (a, ()) -> a
runit_bwd :: a -> (a, ())
Typeclass dan hukum-hukumnya dapat ditulis seperti ini:
class Functor f => Applicative f
where
zip :: (f a, f b) -> f (a, b)
husk :: () -> f ()
-- Laws:
-- assoc_fwd >>> bimap id zip >>> zip
-- =
-- bimap zip id >>> zip >>> fmap assoc_fwd
-- lunit_fwd
-- =
-- bimap husk id >>> zip >>> fmap lunit_fwd
-- runit_fwd
-- =
-- bimap id husk >>> zip >>> fmap runit_fwd
Orang mungkin bertanya-tanya seperti apa fungsi yang oplax monoidal sehubungan dengan struktur yang sama terlihat seperti:
class Functor f => OpApplicative f
where
unzip :: f (a, b) -> (f a, f b)
unhusk :: f () -> ()
-- Laws:
-- assoc_bwd <<< bimap id unzip <<< unzip
-- =
-- bimap unzip id <<< unzip <<< fmap assoc_bwd
-- lunit_bwd
-- =
-- bimap unhusk id <<< unzip <<< fmap lunit_bwd
-- runit_bwd
-- =
-- bimap id unhusk <<< unzip <<< fmap runit_bwd
Jika kita berpikir tentang tipe-tipe yang terlibat dalam definisi dan hukum, kebenaran yang mengecewakan terungkap; OpApplicativetidak lebih spesifik daripada kendala Functor:
instance Functor f => OpApplicative f
where
unzip fab = (fst <$> fab, snd <$> fab)
unhusk = const ()
Namun, sementara setiap Applicativefunctor (benar-benar, ada Functor) sepele OpApplicative, belum tentu ada hubungan yang baik antara Applicativekelemahan dan OpApplicativeoplaxities. Jadi kita dapat mencari functor monoid yang kuat dengan struktur monoid cartesian:
class (Applicative f, OpApplicative f) => StrongApplicative f
-- Laws:
-- unhusk . husk = id
-- husk . unhusk = id
-- zip . unzip = id
-- unzip . zip = id
Hukum pertama di atas adalah sepele, karena satu-satunya penghuni jenis () -> ()ini adalah fungsi identitas ().
Namun, tiga undang-undang yang tersisa, dan karenanya subkelas itu sendiri, tidak sepele. Secara khusus, tidak setiap Applicativecontoh turunan dari kelas ini.
Berikut adalah beberapa Applicativefungsi yang kami dapat nyatakan hal-hal yang sah dari StrongApplicative:
IdentityVoidF(->) r(Lihat jawaban)Monoid m => (,) mVec (n :: Nat)Stream(tak terbatas)
Dan di sini ada beberapa Applicativeyang kita tidak bisa:
[]Either eMaybeNonEmptyList
Pola di sini menunjukkan bahwa StrongApplicativekelas dalam arti tertentu adalah FixedSizekelas, di mana "ukuran tetap" * berarti bahwa multiplisitas ** penduduk adalam suatu penduduk f aadalah tetap.
Ini dapat dinyatakan sebagai dua dugaan:
- Setiap
Applicativemewakili wadah "ukuran tetap" elemen dari argumen jenisnya adalah turunan dariStrongApplicative - Tidak ada contoh
StrongApplicativeada di mana jumlah kejadianadapat bervariasi
Adakah yang bisa memikirkan contoh tandingan yang menyangkal dugaan ini, atau beberapa alasan meyakinkan yang menunjukkan mengapa itu benar atau salah?
* Saya menyadari bahwa saya belum mendefinisikan kata sifat "ukuran tetap" dengan benar. Sayangnya tugasnya agak melingkar. Saya tidak tahu deskripsi formal dari wadah "ukuran tetap", dan saya mencoba untuk membuat satu. StrongApplicativeadalah upaya terbaik saya sejauh ini.
Untuk mengevaluasi apakah ini definisi yang baik, saya perlu membandingkannya. Diberikan beberapa definisi formal / informal tentang apa artinya bagi functor untuk memiliki ukuran atau multiplisitas yang diberikan sehubungan dengan penduduk dari argumen tipenya, pertanyaannya adalah apakah keberadaan sebuah StrongApplicativeinstance secara tepat membedakan functors dari fixed dan berbagai ukuran.
Karena tidak mengetahui definisi formal yang ada, saya memohon intuisi dalam penggunaan istilah "ukuran tetap". Namun jika seseorang sudah mengetahui formalisme yang ada untuk ukuran functor dan dapat membandingkannya StrongApplicative, itu jauh lebih baik.
** Dengan "multiplisitas" Saya mengacu pada pengertian longgar untuk "berapa banyak" elemen sewenang-wenang dari tipe parameter functor yang terjadi pada penghuni jenis codomain functor. Ini tanpa memperhatikan tipe spesifik dari functor diterapkan, dan karenanya tanpa memperhatikan penghuni spesifik dari tipe parameter.
Tidak tepatnya tentang hal ini telah menyebabkan beberapa kebingungan dalam komentar, jadi inilah beberapa contoh dari apa yang saya anggap ukuran / multiplisitas berbagai fungsi menjadi:
VoidF: diperbaiki, 0Identity: diperbaiki, 1Maybe: variabel, minimum 0, maksimum 1[]: variabel, minimum 0, maksimum tak terbatasNonEmptyList: variabel, minimum 1, maksimum tak terbatasStream: diperbaiki, tak terbatasMonoid m => (,) m: diperbaiki, 1data Pair a = Pair a a: diperbaiki, 2Either x: variabel, minimum 0, maksimum 1data Strange a = L a | R a: diperbaiki, 1
(->) ris dan mereka isomorfik dengan cara yang benar.
(->) r; Anda memerlukan komponen isomorfisma untuk mempertahankan struktur aplikasi yang kuat. Untuk beberapa alasan, Representabletypeclass di Haskell memiliki tabulate . return = returnhukum misterius (yang bahkan tidak masuk akal untuk fungsi non monadik), tetapi memberi kita 1/4 dari kondisi yang perlu kita katakan tabulatedan zipmerupakan morfisme dari kategori monoids yang cocok. . 3 lainnya adalah undang-undang tambahan yang harus Anda tuntut.
tabulatedan indexmerupakan morfisme dari kategori yang cocok ..."
returnbukan masalah serius. cotraverse getConst . Constadalah implementasi default untuk return/ puredalam hal Distributive, dan, karena distribusi / keterwakilan memiliki bentuk tetap, implementasi itu unik.