Saya telah melihat istilah Free Monad muncul setiap sekarang dan kemudian untuk beberapa waktu, tetapi semua orang sepertinya menggunakan / mendiskusikannya tanpa memberikan penjelasan tentang apa itu mereka. Jadi: apa itu monad gratis? (Saya akan mengatakan saya akrab dengan monad dan dasar-dasar Haskell, tetapi hanya memiliki pengetahuan yang sangat kasar tentang teori kategori.)
haskell
monads
free-monad
David
sumber
sumber
Jawaban:
Jawaban Edward Kmett jelas luar biasa. Tapi, ini agak teknis. Berikut ini penjelasan yang mungkin lebih mudah diakses.
Monad gratis hanyalah cara umum untuk mengubah functors menjadi monad. Artinya, mengingat functor
f
Free f
adalah monad. Ini tidak akan sangat berguna, kecuali Anda mendapatkan sepasang fungsiyang pertama memungkinkan Anda "memasuki" monad Anda, dan yang kedua memberi Anda cara untuk "keluar" darinya.
Lebih umum, jika X adalah Y dengan beberapa hal tambahan P, maka "X gratis" adalah cara untuk mendapatkan dari Y ke X tanpa mendapatkan tambahan apa pun.
Contoh: monoid (X) adalah himpunan (Y) dengan struktur ekstra (P) yang pada dasarnya mengatakan ia memiliki operasi (Anda dapat memikirkan penambahan) dan beberapa identitas (seperti nol).
Begitu
Sekarang, kita semua tahu daftar
Nah, mengingat jenis apa pun yang
t
kita tahu itu[t]
adalah monoiddan daftar adalah "monoid gratis" atas set (atau dalam tipe Haskell).
Oke, jadi monad gratis adalah ide yang sama. Kami mengambil functor, dan mengembalikan monad. Bahkan, karena monad dapat dilihat sebagai monoids dalam kategori endofunctors, definisi daftar
terlihat sangat mirip dengan definisi monads gratis
dan
Monad
instance memiliki kesamaan denganMonoid
instance untuk daftarsekarang, kami mendapatkan dua operasi kami
sumber
Free f a = Pure a | Roll (f (Free f a))
sebagaiFree f a = a + fa + ffa + ...
, yaitu "f diterapkan pada sejumlah kali". KemudianconcatFree
(yaitujoin
) mengambil "f diterapkan beberapa kali ke (f diterapkan beberapa kali ke a)" dan mengurangkan dua aplikasi yang bersarang menjadi satu. Dan>>=
mengambil "f diterapkan beberapa kali ke" dan "bagaimana untuk pergi dari a ke (b dengan f diterapkan beberapa kali)", dan pada dasarnya menerapkan yang terakhir ke a di dalam yang pertama dan meruntuhkan sarang. Sekarang saya sendiri mengerti!concatFree
pada dasarnyajoin
?Inilah jawaban yang bahkan lebih sederhana: Monad adalah sesuatu yang "menghitung" ketika konteks monadik dihancurkan oleh
join :: m (m a) -> m a
(mengingat yang>>=
dapat didefinisikan sebagaix >>= y = join (fmap y x)
). Ini adalah cara Monads membawa konteks melalui rantai perhitungan berurutan: karena pada setiap titik dalam rangkaian, konteks dari panggilan sebelumnya dihancurkan dengan yang berikutnya.Sebuah monad bebas memenuhi semua hukum Monad, tetapi tidak melakukan runtuh (yaitu, perhitungan). Itu hanya membangun serangkaian konteks bersarang. Pengguna yang menciptakan nilai monadik bebas bertanggung jawab untuk melakukan sesuatu dengan konteks bersarang tersebut, sehingga makna komposisi tersebut dapat ditangguhkan hingga setelah nilai monadik dibuat.
sumber
Foo bebas merupakan hal paling sederhana yang memenuhi semua hukum 'foo'. Dengan kata lain itu memenuhi hukum yang diperlukan untuk menjadi foo dan tidak ada yang ekstra.
Functor pelupa adalah salah satu yang "lupa" bagian dari struktur saat berjalan dari satu kategori ke yang lain.
Fungsi yang diberikan
F : D -> C
, danG : C -> D
, kita katakanF -| G
,F
dibiarkan bersebelahan denganG
, atau berbelok keG
kananF
setiap kali, a: bF a -> b
adalah isomorfika -> G b
, di mana panah berasal dari kategori yang sesuai.Secara formal, functor gratis dibiarkan berdekatan dengan functor yang pelupa.
Monoid Gratis
Mari kita mulai dengan contoh sederhana, monoid gratis.
Ambil monoid, yang didefinisikan oleh beberapa operator set
T
, fungsi biner untuk mash sepasang elemen bersama-samaf :: T → T → T
, danunit :: T
, seperti bahwa Anda memiliki hukum asosiatif, dan hukum identitas:f(unit,x) = x = f(x,unit)
.Anda dapat membuat functor
U
dari kategori monoids (di mana panah adalah homomorfisma monoid, yaitu, mereka memastikan mereka memetakanunit
keunit
monoid lain, dan bahwa Anda dapat menyusun sebelum atau setelah pemetaan ke monoid lain tanpa mengubah makna) ke kategori set (di mana panah hanya panah fungsi) yang 'lupa' tentang operasi danunit
, dan hanya memberi Anda set operator.Kemudian, Anda dapat mendefinisikan functor
F
dari kategori set kembali ke kategori monoids yang dibiarkan bersebelahan dengan functor ini. Functor itu adalah functor yang memetakan seta
ke monoid[a]
, di manaunit = []
, danmappend = (++)
.Jadi untuk meninjau contoh kita sejauh ini, di pseudo-Haskell:
Kemudian untuk menunjukkan
F
itu gratis, kita perlu menunjukkan bahwa itu dibiarkan bersebelahan denganU
, sebuah fungsi yang pelupa, yaitu, seperti yang kita sebutkan di atas, kita perlu menunjukkan bahwaF a → b
isomorfik untuka → U b
sekarang, ingat bahwa target
F
berada dalam kategoriMon
monoids, di mana panah adalah homomorfisma monoid, jadi kita perlu untuk menunjukkan bahwa homomorfisma monoid[a] → b
dapat digambarkan secara tepat dengan fungsi daria → b
.Dalam Haskell, kita menyebut sisi dari ini yang hidup dalam
Set
(eh,,Hask
kategori tipe Haskell yang kita pura-pura adalah Set), adilfoldMap
, yang ketika dikhususkanData.Foldable
untuk dari memiliki tipeMonoid m => (a → m) → [a] → m
.Ada konsekuensi yang mengikuti dari ini menjadi tambahan. Khususnya jika Anda lupa maka membangun dengan gratis, lalu lupakan lagi, sama seperti Anda lupa sekali, dan kita bisa menggunakan ini untuk membangun monadik bergabung. sejak
UFUF
~U(FUF)
~UF
, dan kita bisa lulus dalam homomorfisma identitas monoid dari[a]
ke[a]
melalui isomorfisma yang mendefinisikan adjunction kami, mendapatkan bahwa daftar isomorfisma dari[a] → [a]
adalah fungsi dari jenisa -> [a]
, dan ini hanya kembali untuk daftar.Anda dapat menyusun semua ini lebih langsung dengan menggambarkan daftar dalam istilah ini dengan:
Monad Gratis
Jadi, apa itu Monad Gratis ?
Ya, kami melakukan hal yang sama dengan yang kami lakukan sebelumnya, kami mulai dengan functor U yang pelupa dari kategori monad di mana panah adalah homomorfisma monad ke kategori endofunctor di mana panah adalah transformasi alami, dan kami mencari functor yang dibiarkan berdekatan untuk itu.
Jadi, bagaimana ini berhubungan dengan gagasan tentang monad gratis seperti yang biasanya digunakan?
Mengetahui bahwa sesuatu adalah monad bebas
Free f
,, memberitahu Anda bahwa memberi homomorfisme monad dariFree f -> m
, adalah hal yang sama (isomorfik ke) dengan memberikan transformasi alami (homomorfisme functor) darif -> m
. IngatF a -> b
harus isomorfik agara -> U b
F dibiarkan bersebelahan dengan U. U di sini memetakan monad ke functors.F setidaknya isomorfis dengan
Free
tipe yang saya gunakan dalamfree
paket saya tentang peretasan.Kita juga dapat membangunnya dalam analogi yang lebih ketat dengan kode di atas untuk daftar gratis, dengan mendefinisikan
Cofree Comonads
Kita dapat membangun sesuatu yang serupa, dengan melihat adjoint yang tepat ke functor yang pelupa dengan asumsi itu ada. Sebuah functor cofree hanyalah adjoin kanan / ke functor pelupa, dan dengan simetri, mengetahui sesuatu adalah comofad cofree sama dengan mengetahui bahwa memberikan homomorfisme comonad dari
w -> Cofree f
adalah hal yang sama seperti memberikan transformasi alami dariw -> f
.sumber
Free Monad (struktur data) adalah untuk Monad (kelas) seperti Daftar (struktur data) ke Monoid (kelas): Ini adalah implementasi sepele, di mana Anda dapat memutuskan setelahnya bagaimana konten akan digabungkan.
Anda mungkin tahu apa itu Monad dan bahwa masing-masing Monad membutuhkan implementasi (
fmap
+ -tang hukum Monad) khusus untuk +join
+return
ataubind
+return
.Mari kita asumsikan Anda memiliki Functor (implementasi dari
fmap
) tetapi sisanya tergantung pada nilai dan pilihan yang dibuat saat run-time, yang berarti bahwa Anda ingin dapat menggunakan properti Monad tetapi ingin memilih fungsi Monad sesudahnya.Itu dapat dilakukan dengan menggunakan Free Monad (struktur data), yang membungkus Functor (tipe) sedemikian rupa sehingga
join
lebih merupakan susunan fungsi-fungsi tersebut daripada pengurangan.Yang asli
return
danjoin
yang ingin Anda gunakan, sekarang dapat diberikan sebagai parameter ke fungsi reduksifoldFree
:Untuk menjelaskan jenisnya, kita dapat mengganti
Functor f
denganMonad m
danb
dengan(m a)
:sumber
Monad gratis Haskell adalah daftar functors. Membandingkan:
Pure
analog denganNil
danFree
analog denganCons
. Monad gratis menyimpan daftar fungsi alih-alih daftar nilai. Secara teknis, Anda bisa mengimplementasikan monad gratis menggunakan tipe data yang berbeda, tetapi implementasi apa pun harus isomorfis dengan yang di atas.Anda menggunakan monad gratis setiap kali Anda membutuhkan pohon sintaksis abstrak. Functor dasar dari monad gratis adalah bentuk setiap langkah dari pohon sintaks.
Pos saya , yang sudah ditautkan oleh seseorang, memberikan beberapa contoh cara membangun pohon sintaksis abstrak dengan monad gratis
sumber
Saya pikir contoh nyata yang sederhana akan membantu. Misalkan kita memiliki functor
dengan jelas
fmap
. MakaFree F a
adalah jenis pohon yang daunnya memiliki jenisa
dan yang node ditandai denganOne
,Two
,Two'
danThree
.One
-node memiliki satu anak,Two
- danTwo'
-nodes memiliki dua anak danThree
-nodes memiliki tiga anak dan juga ditandai denganInt
.Free F
adalah monad.return
petax
ke pohon yang hanya daun dengan nilaix
.t >>= f
melihat masing-masing daun dan menggantinya dengan pohon. Ketika daun memiliki nilaiy
itu menggantikan daun itu dengan pohonf y
.Diagram membuat ini lebih jelas, tetapi saya tidak memiliki fasilitas untuk menggambarnya dengan mudah!
sumber