The Applicative
typeclass 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; OpApplicative
tidak lebih spesifik daripada kendala Functor
:
instance Functor f => OpApplicative f
where
unzip fab = (fst <$> fab, snd <$> fab)
unhusk = const ()
Namun, sementara setiap Applicative
functor (benar-benar, ada Functor
) sepele OpApplicative
, belum tentu ada hubungan yang baik antara Applicative
kelemahan dan OpApplicative
oplaxities. 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 Applicative
contoh turunan dari kelas ini.
Berikut adalah beberapa Applicative
fungsi yang kami dapat nyatakan hal-hal yang sah dari StrongApplicative
:
Identity
VoidF
(->) r
(Lihat jawaban)Monoid m => (,) m
Vec (n :: Nat)
Stream
(tak terbatas)
Dan di sini ada beberapa Applicative
yang kita tidak bisa:
[]
Either e
Maybe
NonEmptyList
Pola di sini menunjukkan bahwa StrongApplicative
kelas dalam arti tertentu adalah FixedSize
kelas, di mana "ukuran tetap" * berarti bahwa multiplisitas ** penduduk a
dalam suatu penduduk f a
adalah tetap.
Ini dapat dinyatakan sebagai dua dugaan:
- Setiap
Applicative
mewakili wadah "ukuran tetap" elemen dari argumen jenisnya adalah turunan dariStrongApplicative
- Tidak ada contoh
StrongApplicative
ada di mana jumlah kejadiana
dapat 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. StrongApplicative
adalah 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 StrongApplicative
instance 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
(->) r
is dan mereka isomorfik dengan cara yang benar.
(->) r
; Anda memerlukan komponen isomorfisma untuk mempertahankan struktur aplikasi yang kuat. Untuk beberapa alasan, Representable
typeclass di Haskell memiliki tabulate . return = return
hukum misterius (yang bahkan tidak masuk akal untuk fungsi non monadik), tetapi memberi kita 1/4 dari kondisi yang perlu kita katakan tabulate
dan zip
merupakan morfisme dari kategori monoids yang cocok. . 3 lainnya adalah undang-undang tambahan yang harus Anda tuntut.
tabulate
dan index
merupakan morfisme dari kategori yang cocok ..."
return
bukan masalah serius. cotraverse getConst . Const
adalah implementasi default untuk return
/ pure
dalam hal Distributive
, dan, karena distribusi / keterwakilan memiliki bentuk tetap, implementasi itu unik.