Aplikasi menulis, monads tidak.
Apa maksud pernyataan di atas? Dan kapan yang satu lebih disukai daripada yang lain?
haskell
functional-programming
monads
monad-transformers
applicative
missingfaktor
sumber
sumber
Applicative
s sebenarnya seluruh keluarga dariMonad
s, yaitu satu untuk setiap "bentuk" dari struktur yang mungkin.ZipList
bukan aMonad
, tapiZipList
s dengan panjang tetap adalah.Reader
adalah kasus khusus yang nyaman (atau apakah itu umum?) di mana ukuran "struktur" ditetapkan sebagai kardinalitas jenis lingkungan.Reader
monad hingga isomorfisme. Setelah Anda memperbaiki bentuk wadah, itu secara efektif mengkodekan fungsi dari posisi, seperti memo trie. Peter Hancock menyebut fungsionalitas seperti itu "Naperian", karena mereka mematuhi hukum logaritma.Jawaban:
Jika kita membandingkan jenisnya
kami mendapatkan petunjuk tentang apa yang memisahkan kedua konsep tersebut. Bahwa
(s -> m t)
dalam tipe(>>=)
menunjukkan bahwa nilai dalams
dapat menentukan perilaku komputasi dalamm t
. Monads memungkinkan interferensi antara nilai dan lapisan komputasi. The(<*>)
Operator memungkinkan tidak ada gangguan seperti: fungsi dan argumen perhitungan tidak bergantung pada nilai-nilai. Ini benar-benar menggigit. Membandingkanyang menggunakan hasil dari beberapa efek untuk memutuskan antara dua perhitungan (mis. meluncurkan rudal dan menandatangani gencatan senjata), sedangkan
yang menggunakan nilai
ab
untuk memilih di antara nilai-nilai dari dua perhitunganat
danaf
, setelah melakukan keduanya, mungkin menghasilkan efek yang tragis.Versi monadik pada dasarnya bergantung pada kekuatan ekstra
(>>=)
untuk memilih penghitungan dari suatu nilai, dan itu bisa jadi penting. Namun, mendukung kekuatan tersebut membuat monad sulit untuk dibuat. Jika kita mencoba membangun 'ikatan ganda'kita sampai sejauh ini, tapi sekarang lapisan kita semua campur aduk. Kami memiliki
n (m (n t))
, jadi kami harus menyingkirkan bagian luarnyan
. Seperti yang dikatakan Alexandre C, kita bisa melakukannya jika kita punya yang cocokuntuk mengubah ke
n
dalam danjoin
ke yang lainn
.'Penerapan ganda' yang lebih lemah jauh lebih mudah untuk didefinisikan
karena tidak ada interferensi antar lapisan.
Sejalan dengan itu, ada baiknya untuk mengenali kapan Anda benar-benar membutuhkan kekuatan ekstra
Monad
s, dan kapan Anda bisa lolos dengan struktur komputasi kaku yangApplicative
mendukung.Perhatikan, ngomong-ngomong, meskipun menyusun monad itu sulit, itu mungkin lebih dari yang Anda butuhkan. Jenis tersebut
m (n v)
menunjukkan komputasi denganm
-efek, kemudian komputasi dengann
-efek kev
-nilai, di manam
-efek selesai sebelumn
-efek dimulai (karena itu diperlukanswap
). Jika Anda hanya inginm
menyisipkan -efek dengann
-efek, maka komposisi mungkin terlalu banyak untuk ditanyakan!sumber
m
dann
Anda selalu dapat menulis trafo monadmt
, dan beroperasi dalamn (m t)
penggunaanmt n t
? Jadi Anda selalu dapat membuat monad, hanya saja lebih rumit, menggunakan transformer?data Free f x = Ret x | Do (f (Free f x))
, laludata (:+:) f g x = Inl (f x) | Tnr (g x)
, dan pertimbangkanFree (m :+: n)
. Itu menunda pilihan bagaimana menjalankan interleavings.Maybe
ini berarti bahwa suatu awalNothing
akan menekan evaluasi dari yanga
kemudian / selanjutnyaJust a
. Apakah ini benar?Monad memang menulis, tetapi hasilnya mungkin bukan monad. Sebaliknya, komposisi dua aplikatif tentu saja aplikatif. Saya curiga maksud dari pernyataan asli adalah bahwa "sifat aplikatif membuat, sedangkan monadness tidak." Diucapkan ulang, "
Applicative
ditutup di bawah komposisi, danMonad
tidak."sumber
Jika Anda memiliki aplikatif
A1
danA2
, maka jenisnyadata A3 a = A3 (A1 (A2 a))
juga aplikatif (Anda dapat menulis contoh seperti itu dengan cara yang umum).Sebaliknya, jika Anda memiliki monad
M1
danM2
jenisnyadata M3 a = M3 (M1 (M2 a))
belum tentu monad (tidak ada implementasi umum yang masuk akal untuk>>=
ataujoin
untuk komposisi).Salah satu contoh dapat berupa tipe
[Int -> a]
(di sini kita membuat konstruktor tipe[]
dengan(->) Int
, keduanya adalah monad). Anda dapat dengan mudah menulisDan itu menggeneralisasi untuk setiap aplikatif:
Tetapi tidak ada definisi yang masuk akal tentang
Jika Anda tidak yakin akan hal ini, pertimbangkan ungkapan ini:
Panjang daftar yang dikembalikan harus ditetapkan sebelumnya sebelum bilangan bulat diberikan, tetapi panjang yang benar tergantung pada bilangan bulat yang disediakan. Jadi, tidak ada
join
fungsi yang benar untuk tipe ini.sumber
IO
tanpa programMonad
akan sangat sulit. :)Menulis monad, http://web.cecs.pdx.edu/~mpj/pubs/RR-1004.pdf
sumber
swap : N M a -> M N a
ContT r m a
tidakm (Cont r a)
norCont r (m a)
, danStateT s m a
secara kasarReader s (m (Writer s a))
.swap
menyiratkan bahwa komposisi memungkinkan keduanya "bekerja sama" entah bagaimana. Juga, perhatikan bahwasequence
kasus khusus "swap" untuk beberapa monad. Jadiflip
sebenarnya.swap :: N (M x) -> M (N x)
menurut saya Anda dapat menggunakanreturns
(fmap
ped yang sesuai ) untuk memasukkan sebuahM
di depan danN
di belakang, pergi dariN (M x) -> M (N (M (N x)))
, kemudian gunakanjoin
komposit untuk mendapatkan milik AndaM (N x)
.Solusi hukum distributif l: MN -> NM sudah cukup
untuk menjamin monadisitas NM. Untuk melihat ini, Anda memerlukan unit dan mult. saya akan fokus pada mult (unitnya adalah unit_N unitM)
Ini tidak menjamin bahwa MN adalah monad.
Pengamatan penting bagaimanapun, mulai berlaku ketika Anda memiliki solusi hukum distributif
jadi, LM, LN dan MN adalah monad. Timbul pertanyaan apakah LMN adalah monad (baik oleh
(MN) L -> L (MN) atau oleh N (LM) -> (LM) N
Kami memiliki struktur yang cukup untuk membuat peta ini. Namun, seperti yang diamati oleh Eugenia Cheng , kita membutuhkan kondisi heksagonal (yang sama dengan presentasi persamaan Yang-Baxter) untuk menjamin monadisitas konstruksi. Padahal, dengan kondisi heksagonal, kedua monad yang berbeda itu bertepatan.
sumber