Monad (funktsional dasturlash) - Monad (functional programming) - Wikipedia

Yilda funktsional dasturlash, a monad dasturlarni tuzishga imkon beruvchi mavhumlikdir umumiy tarzda. Qo'llab-quvvatlovchi tillar monadalarni mavhumlashtirish uchun ishlatishi mumkin qozon plitasi dastur mantig'iga kerak. Monadalar bunga o'zlarini ta'minlash orqali erishadilar ma'lumotlar turi (har bir monad turi uchun ma'lum bir tur), bu ma'lum bir shaklni ifodalaydi hisoblash, biri bilan birga protsedura qiymatlarini o'rash uchun har qanday monad tarkibidagi asosiy tur (hosil qiluvchi a monadik qiymat) va boshqasiga funktsiyalarni yaratish monadik qiymatlarni chiqaradigan (deyiladi monadik funktsiyalar).[1]

Bu monadlarga potentsial bilan ishlash kabi ko'plab muammolarni soddalashtirishga imkon beradi aniqlanmagan qiymatlar (bilan Balki monad), yoki qadriyatlarni moslashuvchan, yaxshi shakllangan holda saqlash ro'yxat (yordamida Ro'yxat Monada bilan dasturchi murakkab funktsiyalar ketma-ketligini qisqacha qilib o'zgartirishi mumkin quvur liniyasi yordamchi ma'lumotlarni boshqarishni qisqartiradigan, oqim oqimi, yoki yon effektlar.[1][2]

Monada tushunchasi ham, atama ham dastlab kelib chiqadi toifalar nazariyasi, bu erda monad a sifatida belgilanadi funktsiya qo'shimcha tuzilishga ega.[a] 1980-yillarning oxiri va 1990-yillarning boshlarida boshlangan tadqiqotlar shuni ko'rsatdiki, monadalar bir-biriga o'xshamaydigan kompyuter fanlari muammolarini birlashtirilgan, funktsional model ostida olib kelishi mumkin. Kategoriya nazariyasi shuningdek ma'lum bo'lgan bir nechta rasmiy talablarni taqdim etadi monad qonunlari, bu har qanday monada tomonidan qondirilishi kerak va ishlatilishi mumkin tasdiqlang monadik kod.[3][4]

Monadalar qilishadi semantik hisoblashning bir turi uchun aniq, ular qulay til xususiyatlarini amalga oshirish uchun ham ishlatilishi mumkin. Kabi ba'zi tillar Xaskell, hattoki o'zlarining oldindan tuzilgan ta'riflarini taklif eting kutubxonalar umumiy monad tuzilishi va oddiy misollar uchun.[1][5]

Umumiy nuqtai

"Monad uchun M, turdagi qiymat M a turdagi qiymatga kirishni anglatadi a monad kontekstida. "- C. A. Makkann[6]

Monada a bilan belgilanadi turi konstruktori M ikkita operatsiya bilan birga:

  • return :: a -> M a (shuningdek, deyiladi birlik) har qanday turdagi qiymatni o'raydigan a ichiga monadik qiymat turdagi M a,
  • qo'shilish :: M (M a) -> M a (shuningdek, deyiladi tarkibi) har qanday o'ralgan turdagi monadik qiymatni ochadigan M (M a) tipning oddiy monadik qiymatiga M a.

Turi konstruktori M Bundan tashqari, a deb taxmin qilinadi funktsiya, ya'ni ta'minlash fmap :: (a -> b) -> M a -> M b, esa qaytish va qo'shilish quyida ko'rsatilgan tabiiy muvofiqlik munosabatlarini qondirishi kerak.

Amalda monadalar odatda ular orqali aniqlanadi bog'lash o'rniga operator, infiks belgisi bilan yozilgan >>=:

  • bog'lash :: M a -> (a -> M b) -> M b monadik turini xaritada aks ettiradigan M a monadik turga M b tipning monadik funktsiyasi berilgan a -> M b.

Shuni ham unutmangki bog'lash yoki qo'shilish monadani aniqlash qat'iy ravishda tengdir:

  • Xaritalar a -> M b funktsional ravishda M a -> M (M b) va qo'shilish M (M b) ga M b , majburiy ma >> = f orqali tiklanadi qo'shilish (fmap f ma).
  • O'zaro, ruxsat berish a = M b , shaxsni tasdiqlovchi xaritalar a = M b ga M b Shuning uchun; ... uchun; ... natijasida qo'shilish mmb sifatida tiklanadi mmb >> = id, bu erda identifikatsiya xaritasi.

Foydalanish

Monadalar dasturchiga a ga o'xshash amallar ketma-ketligini tuzishga imkon beradi quvur liniyasi bilan bog'lash ifodalarni bir-biriga bog'laydigan operatorlar. Bunday ketma-ketliklar tabiiy ravishda majburiy tillarning xatti-harakatlarini aks ettiradi, bu erda har bir kod satri o'zgaruvchan deklaratsiyalar va topshiriqlar orqali keyingisiga o'zgartirilgan ijro kontekstidan o'tadigan ko'rsatma hisoblanadi.

The qil Masalan, Haskell-dagi yozuv, monadik kod bloklarini quyidagicha yozishga imkon beradi:

asosiy :: IO ()asosiy = qil ism <- getLine                    - getLine :: IO String          putStrLn ("Salom" ++ ism ++ "!")    - putStrLn :: String -> IO ()

In IO monad, yuqoridagi majburiylikka teng getLine >> = (putStrLn. salom) qayerda salom nomi = "Salom" ++ ism ++ "!". Yozish qil kod bloklari bizga majburiy kodning o'qilishi uchun qarz olishga imkon beradi. Foydalanish bog'lash ammo sof funktsiya quvurlarini yozishga undaydi.

Amaliyotlar ketma-ketligi monadalarning kompyuter faniga eng kuchli tatbiq etuvchisi bo'lib tuyulsa-da, holatlar, yon ta'sirlar va I / U operatsiyalarini ko'rib chiqishda, kontseptsiya ancha umumiy va misol uchun juda oddiy misollar ko'p. Ro'yxat va Balki monadalar. Nozikroq O'quvchi barcha funktsiyalar turlarini tavsiflovchi monad s -> a umumiy manbadan s, kabi boshqa ko'plab monadalar uchun yana bir kanonik misol va tarkibiy model Shtat va IO.

Ro'yxat monadasi

Ro'yxatlar monadaning birinchi namunasini beradi. Demak, mavhum ta'rifiga qaramay, monadalar aksariyat dasturlash tillari uchun juda oddiy ma'lumotlar turi bilan mujassamlangan.

Bilan [a] = A ro'yxati turdagi elementlar bilan ro'yxat turini belgilash a, birlik va tarkib Ro'yxatquyidagilar bilan belgilanadi:

  • birlik :: a -> [a] har qanday qiymatga belgilaydi x turdagi a singleton ro'yxati [x] ushbu elementni o'z ichiga olgan,
  • qo'shilish :: [[a]] -> [a] turdagi ro'yxatlar ro'yxatini birlashtiradi [[a]] ularni tekislangan turlar ro'yxatiga qo'shish orqali [a].

O'zining juda soddaligi tufayli ro'yxat monadasi biron bir tarzda universaldir: u assotsiativ operatsiya tomonidan tarkibni kutadigan har qanday atamalar ketma-ketligini aks ettirishi mumkin.

Masalan, funktsiyani ko'rib chiqing quvur: [b -> b] -> b -> b, quvur liniyasi sifatida ko'rib chiqiladigan funktsiyalar ro'yxatini tuzish. Ichki ro'yxatlarni spawned subprocesses uchun metafora deb o'ylash, natijada zanjirli jarayonni shakllantirishning ikkita teng usuli mavjud:

  • quvur . (xarita trubkasi) :: [[b -> b]] -> b -> b
  • quvur . qo'shilish :: [[b -> b]] -> b -> b

Ushbu ekvivalentlik aks ettiradi assotsiativlik ning (.): qavslar chiqarib tashlanishi mumkin (f. g). h = f. (g. h) = f. g. h, chunki funktsiyalarni tuzish tartibi muhim emas. Bilan ishlash Ro'yxat monad bu xususiyatni to'liq tanib olishga imkon beradi va faqat monadik turdagi qiymatlarni ko'rib chiqishga e'tibor beradi Ro'yxat (b -> b), monadik kompozitsiya bilan ichki ro'yxatlar tabiiy ravishda kamayadi.

Kabi arifmetik amallarga e'tibor bering sum :: [Num] -> Num va prod :: [Num] -> Raqam yuqoridagi misolning sodda o'zgarishini ham taqdim eting. Bu haqiqatning natijasidir (Son, (+), 0), (Raqam, (*), 1)va (b -> b, (.), id) barchasi keng tarqalgan misollardir monoidlar, ya'ni assotsiativ kompozitsion qonuni aniqlangan va birlikka ega bo'lgan bo'shliqlar. Ushbu oddiy tuzilmalarni yodda tutish kerak monadalar o'zlari monoid tushunchasining mavhumligi va shu bilan birga ezoterik, monad - endofunktorlar toifasidagi monoid.

Ning yana bir keng talqini Ro'yxat monada - ning vakili sifatida muqobil, ko'rish [a] tanlangan qiymat uchun mumkin bo'lgan natijalar to'plami sifatida a. Garchi unchalik tabiiy bo'lmasa ham, bu qulay nuqtai nazarni beradi bog'lash elementwise funktsiya dasturidan olingan ro'yxatlarni oddiygina qo'shadigan operator:

  • bog'lash :: [a] -> (a -> [b]) -> [b]

Ushbu rasmda, jarayonning har qanday bitta elementiga bog'langan a mumkin bo'lgan natijalar ro'yxati b, bu majburiy ravishda mumkin bo'lgan qiymatlar ro'yxatidan sanab chiqadi a. Ushbu nuqtai nazardan to'plamlarga ko'proq moslangan til ishlatiladi va ro'yxatlarning tarkibiy tartibini o'tkazib yuboradi. Ammo bu monadik operatsiyalarni tushunishda foydali bo'lishi mumkin.

Masalan, quyidagilarni ko'rib chiqing poweret funktsiyasi, berilgan ro'yxatning barcha sublistlarini qaytarish:

poweret :: [a] -> [[a]]poweret [] = [[]]poweret (x:xs) = qil            ys <- poweret xs       - ys :: [a]    [x:ys, ys]              - x ni qo'ying yoki qo'ymang

Uning qil blokni amalga oshirish, unga teng PowerSet (x: xs) = PowerSet xs >> = ( ys -> [x: ys, ys]), ning ekspresivligini aks ettiradibog'lash.

Misol: Balki

Monadalar bilan dasturlashni rag'batlantirish uchun tezkor psevdokodga misol keltirilgan. Belgilanmagan qiymatlar yoki operatsiyalar - bu ishonchli dasturiy ta'minot tayyorlab qo'yishi va muomala qilishi kerak bo'lgan alohida muammo.

Ushbu maqsad sari birinchi qadam an yaratish bo'lishi mumkin variant turi bu qiymatni biron bir qiymatga ega deb belgilaydi T (T har qanday bo'lishi mumkin) yoki hech qanday qiymatga ega emas. Yangi turi chaqiriladi Balki T va ushbu turdagi qiymatlar turdagi qiymatni o'z ichiga olishi mumkin Tyoki bo'sh qiymat bo'ling Hech narsa yo'q. Qiymat X turdagi T kontekstida aniqlangan, ammo ishlatilgan Balki deb nomlanadi Faqat X. Bu o'zgarmaydigan belgilangan qiymatga ega bo'lgan holatlar va unday bo'lmagan holatlarni farqlash orqali chalkashliklarni oldini olish uchun qilingan.

ma'lumotlar Balki T  =  Faqat T yoki Hech narsa yo'q

Balki T turini o'rash, "o'rash" turi deb tushunish mumkin T Istisno sabablari haqida hech qanday ma'lumotga ega bo'lmagan holda, o'rnatilgan istisno muomalasi bilan yangi turga.

Quyidagi kodda o'zgaruvchilar o'zgaruvchisi bilan qo'shilgan m turiga ega Balki T ba'zi turlari uchun T. Masalan, agar o'zgaruvchi bo'lsa mx qiymatni o'z ichiga oladi, bu shunday Faqat x, bu erda o'zgaruvchi x turiga ega T. λx → ... bu noma'lum funktsiya parametr bilan x kimning turi xulosa qilingan va bo'ladi funktsiya tarkibi operator.

Yana bir yaxshilanish, agar funktsiya oddiy boshqarishi mumkin bo'lsa tekshirilgan istisnolar bilan Balki turi, qisqa tutashuv va qaytib kelish Hech narsa yo'q bir marta qadam muvaffaqiyatsiz tugadi, lekin hisoblash muvaffaqiyatli bo'lsa, to'g'ri qiymatni izohsiz qaytaring.

Qo'shimcha funktsiya qo'shish, ikkitasini qo'shganda buni aniq bajaradi Balki qiymatlar, mx va mening, quyidagicha ta'riflanishi mumkin:

 qo'shish : (Balki Raqam, Balki Raqam)  Balki Raqam qo'shish(mx,mening) = ...     agar mx bu Hech narsa yo'q keyin         ... Hech narsa yo'q     boshqa agar mening bu Hech narsa yo'q keyin         ... Hech narsa yo'q     boshqa         ... Faqat (x + y)     oxiri agar

Ushbu jarayonni yozish Balki har bir holatda qiymatlar zerikarli bo'lishi mumkin va ko'proq funktsiyalar aniqlanganda yanada kuchayadi. Bosqichlarni zanjirga bog'lash operatsiyasi bu yumshatilishning bir usuli va infix operatori kabi x >> = y, hatto intuitiv ravishda har bir qadamdan keyingi bosqichga (ehtimol aniqlanmagan) natijani ko'rsatishi mumkin. Har bir natija texnik jihatdan boshqasiga kiritilganligi sababli funktsiyaammo, operator parametr uchun funktsiyani oladi. Sifatida qo'shish allaqachon uning chiqish qiymatining turini belgilaydi, operatorni moslashuvchan ushlab turish va ularning turlaridan har xil turdagi chiqadigan funktsiyalarni qabul qilish zarar ko'rmasligi kerak:

 >>= : (Balki T, T  Balki U)  Balki U (mx >>= f) = ...     agar mx bu (Faqat x) keyin         ... f(x)    - f, ehtimol U tipidagi belgilangan qiymatini qaytaradi     boshqa         ... Hech narsa yo'q - f qiymat bermaydi     oxiri agar

Bilan >>= mavjud, qo'shish endi juda ixcham narsa sifatida qayta belgilanishi mumkin:

 qo'shish(mx,mening)  =  mx >>= λx -> (mening >>= λy -> Faqat (x + y))

Bu ixchamroq, ammo biroz ko'proq tahlil qilish yanada kuchli narsani ochib beradi. Bittasi uchun bu yagona rol Faqat o'ynaydi qo'shish asosiy qiymatni "a" deb belgilashdir Balki qiymat. Qanday qilib ta'kidlash uchun Faqat harakat qiladi uni o'rash orqali asosiy qiymatga ko'ra uni funktsiya sifatida qayta aniqlash mumkin va boshqalar hozircha:

 va boshqalar : T  Balki T va boshqalar(x)  =  Faqat x

Katta rasm shundaki, bu ikkita funktsiya >>= va va boshqalar soddalashtirish uchun mo'ljallangan edi qo'shish, lekin ular aniq xususiyatlarga bog'liq emas qo'shish yilda har qanday yo'l, faqat Balki Ushbu funktsiyalar, aslida, ning har qanday qiymatlari va funktsiyalariga taalluqli bo'lishi mumkin Balki Masalan, asosiy qadriyatlarning turlaridan qat'i nazar, masalan, qisqacha YO'Q operator (Kleene's) dan uchlik mantiq aniqlanmagan qiymatlarni avtomatlashtirish uchun bir xil funktsiyalardan foydalanadigan:

trinot : Balki Mantiqiy  Balki Mantiqiytrinot(MP)  =  MP >>= .p -> (va boshqalar  emas) p

Bu chiqadi Balki bilan birga yozing >>= va va boshqalarBoshqa monadalar turli xil mantiqiy jarayonlarni o'zida mujassam etgan va ba'zilari qo'shimcha xususiyatlarga ega bo'lishi mumkin bo'lsa-da, ularning barchasi ushbu misolning asosiy konturiga amal qilgan uchta (to'g'ridan-to'g'ri yoki bilvosita) tarkibiy qismlarga ega bo'ladi.[1][7]

Ta'rif

Yuqoridagi misolda ishlatilgan funktsional dasturlashda monada uchun keng tarqalgan ta'rif, aslida a ga asoslangan Kleisli uch marta toifalar nazariyasining standart ta'rifidan ko'ra. Ikkala konstruktsiya matematik jihatdan teng bo'lib chiqadi, shuning uchun har ikkala ta'rif ham to'g'ri monadga ega bo'ladi. Har qanday aniq belgilangan, asosiy turlarni hisobga olgan holda T, U, monada uch qismdan iborat:

  • A turi konstruktori M monadik tipni yaratadigan M T[b]
  • A turi konvertori, tez-tez chaqiriladi birlik yoki qaytish, ob'ektni joylashtiradigan x monada:
    birlik (x): T → M T[c]
  • A kombinator odatda chaqiriladi bog'lash (kabi) o'zgaruvchini bog'lash ) va an bilan ifodalangan infix operatori >>=, bu monadik o'zgaruvchini ochib, keyin uni monadik funktsiya / ifodaga qo'shadi va natijada yangi monadik qiymat paydo bo'ladi:
    (mx >> = f): (M T, T → M U) → M U[d]

Monad sifatida to'liq tan olinish uchun ushbu uchta qism bir nechta qonunlarga rioya qilishlari kerak:

  • birlik a chap shaxs uchun bog'lash:
    birlik (a) >> = = xx → f (x) f (a)
  • birlik uchun ham huquqdir bog'lash:
    ma >> = λx → birlik (x) ma
  • bog'lash mohiyatan assotsiativ:[e]
    ma >> = λx → (f (x) >> = λy → g (y)) (ma >> = -x → f (x)) >> = -y → g (y)[1]

Algebraik ravishda, bu har qanday monada ham toifani keltirib chiqaradi degan ma'noni anglatadi ( Kleisli toifasi ) va a monoid funktsiyalar toifasida (qiymatlardan hisoblashgacha), ikkilik operator sifatida monadik tarkibga ega va birlik shaxs sifatida.[iqtibos kerak ]

Foydalanish

Monad naqshining qiymati shunchaki kondensatsiya kodidan tashqarida va matematik fikrlash bilan bog'lanishni ta'minlaydi. dasturlash paradigmasi ishlab chiquvchi foydalanadi, monad naqshiga rioya qilish ko'plab afzalliklarga olib keladi sof funktsional dasturlash.Men reming hisoblashning o'ziga xos turi, nafaqat monad kapsulaga soladi bu hisoblash naqshining zerikarli tafsilotlari, lekin buni a deklarativ monadik qiymatlar nafaqat hisoblash qiymatlarini, balki hisoblanganligini ham aniq ifodalaydi effektlar, monadik ifodani uning qiymati bilan almashtirish mumkin mos ravishda shaffof pozitsiyalar, shunga o'xshash sof iboralar kabi ko'plab texnikalar va optimallashtirishga imkon beradi qayta yozish.[4]

Odatda, dasturchilar foydalanadilar bog'lash monadik funktsiyalarni ketma-ketlikda zanjirga bog'lash, bu esa ba'zilarga monadalarni "programlanadigan nuqta-vergul" deb ta'riflashga olib keldi, bu ularning soni majburiy tillar ajratish uchun nuqta-verguldan foydalanadi bayonotlar.[1][5]Shunga qaramay, shuni ta'kidlash kerakki, monadalar aslida hisoblashlarga buyurtma bermaydilar; hatto ularni markaziy funktsiyalar sifatida ishlatadigan tillarda ham sodda funktsiya tarkibi dastur doirasini tartibga solishi mumkin.Monadaning umumiy yordam dasturi, aksincha, dastur tuzilishini soddalashtirish va takomillashtirishdan iborat tashvishlarni ajratish abstraktsiya orqali.[4][9]

Monad tuzilishini noyob matematik va sifatida ham ko'rish mumkin vaqtni tuzish o'zgarishi dekorativ naqsh.Ba'zi monadalar funktsiyalar uchun mavjud bo'lmagan qo'shimcha ma'lumotlarni uzatishi mumkin, ba'zilari esa, masalan, faqat ma'lum bir sharoitda funktsiyani chaqirishga, masalan, bajarilish ustidan nozikroq nazoratni amalga oshirishi mumkin. domen mantig'i qozon plitasining kodini oldindan ishlab chiqilgan modullarga tushirish paytida, monadalarni hatto vosita deb hisoblash mumkin aspektga yo'naltirilgan dasturlash.[10]

Monadlar uchun yana bir e'tiborga loyiq usullardan biri bu yon ta'sirlarni ajratishdir kirish / chiqish yoki o'zgaruvchan davlat, aks holda faqat funktsional kodda mumkin hali ham ushbu "nopok" hisob-kitoblarni monadalarsiz, funktsional tarkibi va davom ettirish uslubi (CPS), xususan.[2]Monadalar bilan birga, bu iskala ko'p qismini, asosan, CPS kodidagi har bir takrorlanadigan naqshni olish va uni alohida monadga to'plash orqali olib tashlash mumkin.[4]

Agar til monadlarni sukut bo'yicha qo'llab-quvvatlamasa, odatda juda qiyin bo'lmagan holda naqshni amalga oshirish mumkin. umumiy tushuncha va to'g'ridan-to'g'ri ekvivalent xususiyatni qo'llab-quvvatlaydigan har qanday tilda aniqlanishi mumkin chegaralangan polimorfizm.Kontseptsiyaning asosiy turlar ustida ishlash paytida operatsion tafsilotlar to'g'risida agnostik bo'lib qolish qobiliyati kuchli, ammo monadalarning o'ziga xos xususiyatlari va qat'iy xatti-harakatlari ularni boshqa tushunchalardan ajratib turadi.[11]

Ilovalar

Muayyan monadalarni muhokama qilish, odatda, tor doiradagi muammolarni hal qilishga qaratilgan bo'ladi, chunki berilgan monad ma'lum bir hisoblash shaklini anglatadi, ammo ba'zi holatlarda, dastur o'zining mantiqiy asosidagi tegishli monadlardan foydalangan holda, hatto yuqori darajadagi maqsadlariga ham erishishi mumkin.

Mana, ularning dizayni asosida monadalar mavjud bo'lgan bir nechta dastur:

Tarix

Dasturlashda "monad" atamasi aslida "to" qaytib keladi APL va J dasturiy tillar, ular faqat funktsional bo'lishga moyil. Biroq, o'sha tillarda "monad" faqat bitta parametrni qabul qiladigan funktsiya uchun stenografiyadir (ikkita parametrli funktsiya "dyad" va boshqalar).[17]

Matematik Rojer Godement 1950 yillarning oxirlarida birinchi bo'lib monada kontseptsiyasini shakllantirdi (uni "standart qurilish" deb nomladi), ammo hukmronlik qilgan "monad" atamasi nazariyotchi kategoriya bilan bog'liq Saunders Mac Lane.[iqtibos kerak ] Yordamida yuqorida ko'rsatilgan shakl bog'lashammo, dastlab 1965 yilda matematik tomonidan tasvirlangan Geynrix Kleysli har qanday monadani an sifatida tavsiflash mumkinligini isbotlash uchun birikma ikkita (kovariant) funktsiyalar o'rtasida.[18]

1980-yillardan boshlab kompyuter fanlari hamjamiyatida monada naqsh haqidagi noaniq tushuncha paydo bo'ldi. Filipp Vadler, kompyuter mutaxassisi Jon C. Reynolds qiymatini muhokama qilganida, 1970 va 1980 yillarning boshlarida uning bir nechta qirralarini kutgan davom ettirish uslubi, rasmiy semantikaning boy manbai bo'lgan toifalar nazariyasi va qiymatlar va hisoblashlar o'rtasidagi turlarning farqi.[4]Tadqiqot tili Opal 1990 yilgacha faol ravishda ishlab chiqilgan, shuningdek monadik tipdagi samarali I / O asoslangan edi, lekin o'sha paytda ulanish amalga oshirilmadi.[19]

Kompyutershunos Evgenio Moggi 1989 yilda bo'lib o'tgan konferentsiyada birinchi bo'lib toifalar nazariyasining monadasini funktsional dasturlash bilan aniq bog'lagan,[20] So'ngra 1991 yilda jurnalni yanada takomillashtirilgan holda taqdim etish. Avvalgi ishlarda bir nechta kompyuter olimlari toifalar nazariyasidan foydalanib, semantikani ta'minladilar. lambda hisobi. Moggining asosiy tushunchasi shundan iboratki, haqiqiy dunyo dasturi nafaqat qadriyatlardan boshqa qadriyatlarga funktsiya, balki aksincha shakllanadigan o'zgarishdir. hisoblashlar ushbu qadriyatlar bo'yicha. Kategoriya-nazariy jihatdan rasmiylashtirilganda, bu monadalar ushbu hisob-kitoblarni namoyish etuvchi tuzilma degan xulosaga keladi.[3]

Ushbu g'oyani ommalashtirgan va qurgan yana bir qancha odamlar, shu jumladan Filipp Vadler va Simon Peyton Jons, ikkalasi ham Haskellning spetsifikatsiyasida qatnashgan. Xususan, Haskell v1.2 orqali muammoli "dangasa oqim" modelini I / U bilan moslashtirish uchun ishlatgan dangasa baholash, yanada moslashuvchan monadik interfeysga o'tguncha.[21] Haskell hamjamiyati monadalarni funktsional dasturlashdagi ko'plab muammolarga tatbiq etishni davom ettiradi va Haskell bilan ishlaydigan tadqiqotchilar oxir-oqibat monad naqshini strukturalarning kengroq ierarxiyasida umumlashtirdilar, shu jumladan amaliy funktsiyalar va o'qlar.[iqtibos kerak ]

Dastlab monadalar bilan dasturlash asosan Haskell va uning hosilalari bilan chegaralangan edi, ammo funktsional dasturlash boshqa paradigmalarga ta'sir ko'rsatgani sababli, ko'plab tillarda monad naqsh kiritilgan (nomda bo'lmasa ruhda). Endi formulalar mavjud Sxema, Perl, Python, Raketka, Klojure, Scala, F #, shuningdek, yangi uchun ko'rib chiqilgan ML standart.[iqtibos kerak ]

Tahlil

Monad naqshining afzalliklaridan biri dastur mantig'iga matematik aniqlikni kiritishdir, faqat monad qonunlari misolning haqiqiyligini tekshirish uchun ishlatilishi mumkin emas, balki tegishli tuzilmalar (masalan, funktsiyalar) funktsiyalari orqali foydalanish mumkin kichik tip.

Monad qonunlarini tekshirish

Ga qaytish Balki Masalan, uning tarkibiy qismlari monadani tashkil qilishi e'lon qilingan, ammo monada qonunlarini qondirishiga dalil keltirilmagan.

Buni o'ziga xos xususiyatlarni ulab tuzatish mumkin Balki umumiy qonunlarning bir tomoniga, so'ngra algebraik ravishda boshqa tomonga erishish uchun tengliklar zanjirini yarating:

1-qonun:  eta (a) >> = f (x) ⇔ (shunchaki a) >> = f (x) -f (a)
2-qonun:  ma >> = eta (x) ⇔ ma agar ma bu (Shunchaki a) keyin            eta (a) ⇔ Faqat a boshqa                        yoki            Hech narsa ⇔ Hech narsa tugatish agar
3-qonun:  (ma >> = f (x)) >> = g (y) ⇔ ma >> = (f (x) >> = g (y))        agar (ma >> = f (x)) bu (Faqat b) keyin               agar ma bu (Shunchaki a) keyin            g (ma >> = f (x)) (f (x) >> = g (y)) a boshqa                                            boshqa            Hech narsa Hech narsa tugatish agar                                          tugatish agaragar ma bu (Shunchaki a) va f (a) bu (Faqat b) keyin                             (g-f) a boshqa bo'lsa ma bu (Shunchaki) va f (a) u holda Hech narsa emas                       Hech narsa yo'q boshqa                       Hech narsa yo'q tugatish agar

Dan olingan funktsiyalar

Kompyuter fanida kamdan-kam uchraydigan bo'lsa-da, to'g'ridan-to'g'ri kategoriya nazariyasidan foydalanish mumkin, bu monadani ikkita qo'shimcha funktsiya sifatida belgilaydi tabiiy o'zgarishlar.Shunday qilib, boshlash uchun tuzilish a ni talab qiladi yuqori darajadagi funktsiya (yoki "funktsional") nomlangan xarita funktsiyani bajarish uchun:

xarita φ: (a → b) → (ma → mb)

Biroq, bu har doim ham muhim muammo emas, ayniqsa, agar monad oldindan mavjud bo'lgan funktsiyadan kelib chiqsa, monad meros qilib oladi. xarita avtomatik ravishda. (Tarixiy sabablarga ko'ra, bu xarita o'rniga chaqiriladi fmap Haskellda.)

Monadaning birinchi o'zgarishi aslida bir xil birlik Kleisli uchligi, ammo tuzilmalar ierarxiyasini diqqat bilan kuzatib borganida, u chiqadi birlik xarakterlaydi amaliy funktsiya, monad va asosiy funktsiya o'rtasidagi oraliq tuzilish. Amaliy kontekstda, birlik ba'zan deb nomlanadi toza ammo baribir bir xil funktsiya. Ushbu qurilishda farq qiladigan narsa qonundir birlik qondirishi kerak; kabi bog'lash aniqlanmagan, cheklov atamalari bilan berilgan xarita o'rniga:

(birlik ∘ φ) x ↔ ((xarita φ) ∘ birlik) x[22]

Amaliy funktsiyadan monadaga so'nggi sakrash ikkinchi o'zgarish bilan birga keladi qo'shilish funktsiya (toifalar nazariyasida bu odatda tabiiy o'zgarish deb ataladi m), bu monadaning ichki dasturlarini "tekislaydi":

qo'shilish (mma): M (M T) → M T

Xarakterli funktsiya sifatida, qo'shilish monad qonunlarining uchta o'zgarishini qondirishi kerak:[iqtibos kerak ]

qo'shilish ∘ (xarita qo'shilish) mmma ↔ (qo'shilish ∘ qo'shilish) mmma ↔ ma
birlashtirish ∘ (xarita birligi) ma ↔ (birlashma ∘ birligi) ma ↔ ma
qo'shilish ∘ (xarita xaritasi φ) mma ↔ ((xarita φ) ∘ qo'shilish) mma ↔ mb

Ishlab chiquvchi to'g'ridan-to'g'ri monad yoki Kleisli uchligini belgilashidan qat'i nazar, asosiy tuzilish bir xil bo'ladi va shakllar bir-biridan osonlikcha olinishi mumkin:

(xarita φ) ma ↔ ma >> = (birlik ∘ φ)
qo'shilish (mma) ↔ mma >> = id
ma >> = f ↔ (qo'shiling map (xarita f)) ma[23]

Yana bir misol: Ro'yxat

The murakkab ko'p qiymatli kvadrat va kub ildiz funktsiyalari bo'lishi mumkin tuzilgan shuning uchun ular oltinchi ildiz funktsiyasini ishlab chiqaradilar. Kirish va chiqish turini boshqaradigan tuzilma va turli xil harakatlarni tuzadigan tuzilma, birgalikda, a ro'yxat monad.[24]
The o'q belgisi • belgisini bildiradi bog'lash operator, z murakkab son, kvadrat qavslar esa anni bildiradi qator va: = degani "sifatida belgilanadi ':
(fg)(z) := qo'shib qo'ying(xarita(f,g(z)))ko'tarish(f) = f° := birlikf = fbirlikkv°(z) == qo'shib qo'ying(xarita(birlik,kv(z)))= qo'shib qo'ying(xarita(kv,birlik(z)))sxrt(z) = (cbrt°•kv°)(z) == qo'shib qo'ying(xarita(cbrt°,kv°(z)))
[shubhali ]

The Ro'yxat monad Monadni oddiyroq funktsiyadan qanday qilib olish foydali bo'lishi mumkinligini tabiiy ravishda namoyish etadi.Ko'pgina tillarda ro'yxat tuzilmasi ba'zi bir asosiy xususiyatlar bilan birga oldindan belgilanadi, shuning uchun Ro'yxat turi konstruktor va qo'shib qo'ying operator (bilan ko'rsatilgan ++ infix notation uchun) bu erda allaqachon berilgan deb taxmin qilinadi.

Ro'yxatga oddiy qiymatni kiritish, aksariyat tillarda ahamiyatsiz:

birlik (x) = [x]

Bu erdan funktsiyani a bilan takroriy ravishda qo'llash ro'yxatni tushunish uchun oson tanlov bo'lib tuyulishi mumkin bog'lash va ro'yxatlarni to'liq monadga aylantirish.Bu yondashuvning qiyinligi shundaki bog'lash monadik funktsiyalarni kutadi, bu holda ular o'zlari ro'yxatlarni chiqaradilar; ko'proq funktsiyalar qo'llanilganda, ichki tushuntirilgan ro'yxatlarning qatlamlari to'planib, asosiy tushunishdan ko'proq narsani talab qiladi.

Biroq, har qanday birini qo'llash tartibi oddiy butun ro'yxat bo'yicha, boshqacha qilib aytganda xarita, to'g'ri oldinga:

(xarita φ) xlist = [φ (x1), φ (x2), ..., φ (xn)]

Endi, ushbu ikkita protsedura allaqachon rivojlanmoqda Ro'yxat Monadani to'liq egallash uchun faqat to'g'ri tushunchasi qo'shilish takrorlangan tuzilmani tekislash kerak, ammo ro'yxatlar uchun bu faqat qiymatlarni o'z ichiga olgan ichki qismlarni qo'shish uchun tashqi ro'yxatni ochishni anglatadi:

qo'shilish (xlistlist) = qo'shilish ([xlist1, xlist2, ..., xlistn]) = xlist1 ++ xlist2 ++ ... ++ xlistn

Natijada paydo bo'lgan monad nafaqat ro'yxat, balki funktsiyalar qo'llanilganda avtomatik ravishda o'lchamlarini o'zgartiradigan va zichlashadigan ro'yxatdir.bog'lash endi faqat formuladan kelib chiqib, keyin ovqatlantirish uchun ishlatilishi mumkin Ro'yxat monadik funktsiyalar quvur liniyasi orqali qiymatlar:

(xlist >> = f) = qo'shilish ∘ (xarita f) xlist

Ushbu monadik ro'yxat uchun bitta dastur mavjud nondeterministik hisoblash.Ro'yxat algoritmdagi barcha bajarilish yo'llari uchun natijalarni ushlab turishi mumkin, so'ngra har bir qadamda qaysi yo'llar natijaga olib kelganligini "unutish" uchun o'zini zichlashtirishi mumkin (deterministik, to'liq algoritmlardan ba'zida muhim farq) .Shuningdek, yana bir foyda shundaki, tekshiruvlar monada joylashtirilgan bo'lishi mumkin ; ma'lum bir yo'llar birinchi muvaffaqiyatsizlik nuqtasida shaffof ravishda kesilishi mumkin, bu quvur liniyasidagi funktsiyalarni qayta yozishga hojat yo'q.[23]

Ikkinchi vaziyat qaerda Ro'yxat nashrida kompozitsiyasi ko'p qiymatli funktsiyalar.Masalan, nth murakkab ildiz raqamning hosil bo'lishi kerak n aniq murakkab raqamlar, ammo boshqasi bo'lsa mSo'ngra ushbu natijalardan ildiz olinadi, yakuniy m • n qiymatlari ning chiqishi bilan bir xil bo'lishi kerak m • nildiz.Ro'yxat har bir qadam natijalarini bir tekis, matematik jihatdan to'g'ri ro'yxatga quyib, bu masalani to'liq avtomatlashtiradi.[24]

Texnikalar

Monadalar nafaqat dastur mantig'ini tashkil qilishdan tashqari, qiziqarli texnikalar uchun imkoniyatlarni taqdim etadi. Monadalar foydali sintaktik xususiyatlarga asos yaratishi mumkin, yuqori darajadagi va matematik tabiati esa abstraktsiyaga imkon beradi.

Sintaktik shakar yozuvlar

Garchi foydalanayotgan bo'lsa ham bog'lash ochiqchasiga ko'pincha mantiqiy, ko'plab dasturchilar majburiy so'zlarni taqlid qiladigan sintaksisni afzal ko'rishadi (chaqiriladi) yozuvlar Haskellda, ijro etish yilda OCaml, hisoblash iboralari yilda F #,[25] va tushunish uchun yilda Scala ). Bu faqat sintaktik shakar monadik quvur liniyasini a sifatida yashiradi kod bloki; keyin kompilyator jimgina ushbu iboralarni asosiy funktsional kodga aylantiradi.

Tarjima qilinmoqda qo'shish funktsiyasi Balki ichiga Haskell ushbu xususiyatni amalda ko'rsatishi mumkin. Ning monadik bo'lmagan versiyasi qo'shish Haskellda shunday ko'rinadi:

qo'shish mx mening =    ish mx ning        Hech narsa yo'q -> Hech narsa yo'q        Faqat x  -> ish mening ning                       Hech narsa yo'q -> Hech narsa yo'q                       Faqat y  -> Faqat (x + y)

Monadik Haskellda, qaytish uchun standart nom birlik, shuningdek, lambda ifodalari aniq muomala qilinishi kerak, ammo hattoki ushbu texnik xususiyatlar bilan ham Balki monad yanada toza ta'rifni beradi:

qo'shish mx mening =    mx >>= (\x ->        mening >>= (\y ->            qaytish (x + y)))

Do notasi bilan, buni yanada intuitiv ketma-ketlikda distillash mumkin:

qo'shish mx mening = qil    x <- mx    y <- mening    qaytish (x + y)

Ikkinchi misol qanday amalga oshirilishini ko'rsatadi Balki butunlay boshqacha tilda ishlatilishi mumkin: F #. Hisoblash iboralari bilan "xavfsiz bo'linish" funktsiyasi Yo'q aniqlanmagan operand uchun yoki nolga bo'linish quyidagicha yozilishi mumkin:

ruxsat bering readNum () =  ruxsat bering s = Konsol.ReadLine()  ruxsat bering succ,v = Int32.TryParse(s)  agar (succ) keyin Biroz(v) boshqa Yo'qruxsat bering safe_div =   balki {     ruxsat bering! x = readNum()    ruxsat bering! y = readNum()    agar (y = 0)     keyin Yo'q    boshqa qaytish (x / y)  }

Qurilish vaqtida kompilyator bu funktsiyani ichki zichroq zanjirga aylantiradi bog'lash qo'ng'iroqlar:

balki.Kechiktirish(qiziqarli () ->  balki.Bog'lash(readNum(), qiziqarli x ->    balki.Bog'lash(readNum(), qiziqarli y ->      agar (y=0) keyin Yo'q boshqa balki.Qaytish(x / y))))

So'nggi misol uchun, hatto umumiy monad qonunlarining o'zi ham notada ifodalanishi mumkin:

qil { x <- qaytish v; f x }            ==  qil { f v }qil { x <- m; qaytish x }              ==  qil { m }qil { y <- qil { x <- m; f x }; g y }  ==  qil { x <- m; y <- f x; g y }

Qulay bo'lgan taqdirda, ishlab chiquvchi har doim ushbu blok uslubi faqat sintaktik ekanligini va uni tashqi monadik (yoki hatto monadik bo'lmagan CPS) iboralar bilan almashtirish mumkinligini yodda tutishi kerak. bog'lash monadik quvur liniyasini ifodalash uchun ko'p hollarda aniqroq bo'lishi mumkin va ba'zi funktsional dasturiy himoyachilar, hatto blok uslubi yangi boshlanuvchilarga odatiy dasturlashdan odatlarni olib o'tishga imkon berganligi sababli, uni sukut bo'yicha oldini olish kerak va faqat aniq ustun bo'lgan taqdirda ishlatilishi kerak.[26][1]

Umumiy interfeys

Har qanday monada monad qonunlariga javob beradigan aniq dasturga muhtoj, ammo til ichidagi boshqa tuzilmalar yoki standart iboralar bilan bog'liq boshqa jihatlar barcha monadalar tomonidan baham ko'riladi. Natijada til yoki kutubxona umumiy ma'lumotni taqdim qilishi mumkin. Monad bilan interfeys funktsional prototiplar, munosabatlarning subtipasi va boshqa umumiy faktlar. Ishlab chiqishni boshlash va yangi monadani kafolatlash bilan bir qatorda supertipdan funktsiyalarni oladi (masalan, funktsiyalar), monad dizaynini interfeysga qarab tekshirish sifatni nazorat qilishning yana bir qatlamini qo'shadi.[iqtibos kerak ]

Operatorlar

Monadik kod ko'pincha operatorlardan oqilona foydalanish orqali yanada soddalashtirilishi mumkin xarita funktsional ayniqsa foydali bo'lishi mumkin, chunki u odatdagi monadik funktsiyalardan ko'proq ishlaydi; monadik funktsiya oldindan belgilangan operatorga o'xshash ishlashi kerak ekan, xarita bir zumda ishlatilishi mumkin "ko'tarish "sodda operatorni monadik operatorga aylantirish.[f]Ushbu texnikada, ning ta'rifi qo'shish dan Balki misolni distillangan bo'lishi mumkin:

add (mx, my) = map (+)

Jarayonni aniqlash orqali hatto bir qadam oldinga surish mumkin edi qo'shish nafaqat uchun Balki, lekin umuman Monad interfeysi.Bu bilan tuzilish interfeysiga mos keladigan va o'ziga mos keladigan har qanday yangi monad xarita ning ko'tarilgan versiyasini darhol meros qilib oladi qo'shish Kerakli funktsiyadagi yagona o'zgarish imzo turini umumlashtirishdir:

qo'shish: (Monad raqami, Monad raqami) → Monad raqami[27]

Tahlil uchun foydali bo'lgan yana bir monadik operator - bu monadik kompozitsiya (infiks sifatida ko'rsatilgan) >=> monadik funktsiyalarni yanada matematik uslubda zanjirlashga imkon beradigan:

(f> => g) x = (f (x) → mb) >> = g (y = b)

Ushbu operator bilan monad qonunlari faqat funktsiyalar bo'yicha yozilishi mumkin, bu assotsiativlik va shaxsning mavjudligiga mosligini ta'kidlaydi:

(birlik> => g) -g (f> => birlik) -f f (f> => g)> => h-f> => (g> => h)[1]

O'zgarishlar

Matematik darajadagi ba'zi monadalar ayniqsa yaxshi xususiyatlarga ega va ba'zi bir muammolarga noyob tarzda mos keladi.

Qo'shimcha monadlar

An qo'shimcha monad qo'shimcha yopiq, assotsiativ, ikkilik operator bilan ta'minlangan monada mplus va an hisobga olish elementi ostida mplus, deb nomlangan mzero.The Balki monadni qo'shimchalar deb hisoblash mumkin, bilan Hech narsa yo'q kabi mzero va o'zgaruvchanligi Yoki operatori sifatida mplus.Ro'yxat shuningdek, qo'shimchalar monadasi, bo'sh ro'yxat bilan [] sifatida harakat qilish mzero va biriktirish operatori ++ kabi mplus.

Intuitiv ravishda, mzero monadik o'ramni asosiy turidan hech qanday qiymati bo'lmagan holda ifodalaydi, lekin u "nol" ("bitta" o'rniga) deb hisoblanadi, chunki u absorber uchun bog'lash, qaytib mzero har doim monadik funktsiyaga bog'langan bo'lsa, bu xususiyat ikki tomonlama va bog'lash qaytib keladi mzero har qanday qiymat monadikaga bog'langanda nol funktsiyasi.

Kategoriya-nazariy nuqtai nazardan qo'shimcha monad monadik funktsiyalarga nisbatan monoid sifatida bir marta tanlanadi bog'lash (barcha monadalar kabi) va yana monadik qiymatlar orqali mplus.[28][g]

Bepul monadlar

Ba'zida monadaning umumiy chizmasi foydali bo'lishi mumkin, ammo oddiy naqsh u yoki bu monadani tavsiya etmaydi. bepul monad kirib keladi; kabi bepul ob'ekt monadalar toifasida monadik tuzilmani monad qonunlaridan tashqari har qanday o'ziga xos cheklovlarsiz namoyish etishi mumkin. bepul monoid elementlarni baholashsiz birlashtiradi, erkin monad tipik tizimni qondirish uchun markerlar bilan hisoblashlarni zanjirlashga imkon beradi, aks holda chuqur semantikani o'zi talab qilmaydi.

Masalan, orqali to'liq ishlash orqali Faqat va Hech narsa yo'q markerlar, Balki monad aslida bepul monad.The Ro'yxat monada esa bepul monada emas, chunki u ro'yxatlar haqida qo'shimcha, aniq dalillarni keltirib chiqaradi (masalan qo'shib qo'yingSo'nggi bir misol uchun markerlardan foydalangan holda mavhum bepul monad birlik va bog'lash va rekursiv, chiziqli turdagi konstruktor:

yangi tur Erkin F (T) = birlik T yoki Bind (F, Free F (T)) birlik (x) = birlik xmx >> = f = ... agar mx bu X birligi keyin        ... f (x) boshqa        ... bog'lash (f, mx) tugatish agar

Biroq, bepul monadalar emas Ushbu misoldagi kabi bog'langan ro'yxat bilan cheklangan va shunga o'xshash boshqa tuzilmalar atrofida qurilishi mumkin daraxtlar.

Bepul monadlardan qasddan foydalanish dastlab maqsadga muvofiq emas tuyulishi mumkin, ammo ularning rasmiy tabiati sintaktik muammolar uchun juda mos keladi. Bepul monad sintaksisni kuzatish va keyinchalik semantikani qoldirish uchun ishlatilishi mumkin va tahlilchilarda foydalanishni topdi va tarjimonlar Natijada.[29]Boshqalar ularni yanada dinamik, operatsion muammolarga, masalan, ta'minotga qo'lladilar takrorlanadi til ichida.[30]

Komonadalar

Qo'shimcha xususiyatlarga ega monadalar hosil qilishdan tashqari, har qanday monad uchun a ni aniqlash mumkin komada.Kontseptual ravishda, agar monadalar asosiy qadriyatlar asosida tuzilgan hisob-kitoblarni ifodalasa, u holda komonadalarni qadriyatlargacha pasayish sifatida ko'rish mumkin.Monadik kodni ma'lum ma'noda to'liq "paketdan chiqarib bo'lmaydi"; Agar qiymat monadga o'ralgan bo'lsa, u har qanday nojo'ya ta'sirlar bilan birga karantinada qoladi (sof funktsional dasturlashda yaxshi narsa) .Ba'zida, muammo ko'proq komunadlar aniq modellashtirishi mumkin bo'lgan kontekstli ma'lumotlarni iste'mol qilish bilan bog'liq.

Texnik jihatdan komonad bu ikki tomonlama monadaning ma'nosi, bu bo'shashmasdan, faqat bitta turdagi imzolar yo'nalishi bilan bir xil kerakli tarkibiy qismlarga ega bo'lishini anglatadi teskari.Bundan boshlab bog'lash- markaziy monad ta'rifi, komonad quyidagilardan iborat:

  • Turi konstruktori V bu yuqori darajadagi turni belgilaydi V T
  • Dual birlik, deb nomlangan masjid bu erda asosiy qiymatni komadadan ajratib oling:
Counit (wa): W T → T
  • Orqaga qaytarish bog'lash (bilan ham ifodalangan =>>) bu uzaytirmoqqisqartiruvchi funktsiyalar zanjiri:
(wa = >> f): (W U, W U → T) → W T[h]

uzaytirmoq va masjid monad qonunlarining ikkiliklarini qondirishi kerak:

oun ( (wa = >> f) → wb )  F (wa) → bwa = >> counit ↔ wawa ( (= >> f (wx = wa)) → wb (= >> g (wy = wb)) → wc )( wa (= >> f (wx = wa)) → wb ) (= >> g (wy = wb)) → wc

Monadalarga o'xshash komonadalar funktsiyalardan ikkitadan foydalanib ham olinishi mumkin qo'shilish:

  • dublikat allaqachon komonadik qiymatni oladi va uni boshqa komonadik tuzilish qatlamiga o'raladi:
dublikat (wa): W T → W (W T)

Operatsiyalar kabi uzaytirmoq teskari tomonga o'zgartiriladi, ammo komonad buni amalga oshiradi emas teskari funktsiyalar u ishlaydi va natijada komonadalar hanuzgacha funktsiyalardir xarita, emas kofunktorlar. Bilan muqobil ta'rif dublikat, masjidva xarita o'z komonad qonunlarini ham hurmat qilishi kerak:

((xarita dublikati) ∘ dublikat) wa ↔ (dublikat ∘ dublikat) wa ↔ wwwa ((xarita kounit) ∘ dublikat) wa ↔ (aniqlik dublikati) wa ↔ wa ((xarita xaritasi φ) ∘ dublikat) wa ↔ (dublikat ∘ (xarita φ)) ww wwb

Va monadalar singari, ikkita shakl avtomatik ravishda o'zgartirilishi mumkin:

(xarita φ) wa ↔ wa = >> (φ oun counit) wx nusxa wa ↔ wa = >> wx
wa = >> f (wx) ↔ ((xarita f) ∘ dublikat) wa

Oddiy misol Mahsulot kommadasi, kirish qiymati va umumiy muhit ma'lumotlari asosida qiymatlarni chiqaradi. Aslida Mahsulot comonad shunchaki ikkitadir Yozuvchi monad va samarali bilan bir xil O'quvchi monad (ikkalasi ham quyida muhokama qilinadi).Mahsulot va O'quvchi faqat qaysi funktsiya imzolarini qabul qilishlari va qiymatlarni o'rash yoki ochish orqali ushbu funktsiyalarni qanday to'ldirishlari bilan farqlanadi.

Kamroq ahamiyatsiz misol Oqimli komonad, vakili qilish uchun ishlatilishi mumkin ma'lumotlar oqimlari va kelgan signallarga filtrlarni ulang uzaytirmoq.Aslida, monadalar singari mashhur bo'lmasa-da, tadqiqotchilar komonadlarni ayniqsa foydali deb topishdi oqimlarni qayta ishlash va modellashtirish ma'lumotlar oqimini dasturlash.[31][32]

Ammo ularning qat'iy ta'riflari tufayli monadalar va komonadalar o'rtasida narsalarni oldinga va orqaga siljitish mumkin emas. o'qlar ikkala tuzilmani ham o'zlashtirishi mumkin, ammo monadik va komonadik kodni birlashtirishning yanada donador usullarini topish tadqiqotning faol yo'nalishi hisoblanadi.[33][34]

Ko'proq misollar

Identity monad

Eng oddiy monad bu Identity monad, which just annotates plain values and functions to satisfy the monad laws:

newtype Id T  =  Tunit(x)    =  x(x >>= f)  =  f(x)

Shaxsiyat does actually have valid uses though, such as providing a asosiy ish for recursive monad transformers.It can also be used to perform basic variable assignment within an imperative-style block.[men][iqtibos kerak ]

To'plamlar

Any collection with a proper qo'shib qo'ying is already a free monoid, but it turns out that Ro'yxat is not the only to'plam that also has a well-defined qo'shilish and qualifies as a monad.One can even mutate Ro'yxat into these other monadic collections by simply imposing special properties on qo'shib qo'ying:[j][iqtibos kerak ]

To'plamMonoid properties
Ro'yxatOzod
Cheklangan multisetKommutativ
Cheklangan to'plamCommutative and idempotent
Cheklangan almashtirishlarNon-commutative and idempotent

IO monad (Haskell)

As already mentioned, pure code should not have unmanaged side effects, but that does not preclude a program from aniq describing and managing effects.This idea is central to Haskell's IO monad, where an object of type IO a can be seen as containing the current state of the world outside the program, and computing a value of type a. A computation that computes no value – i.e., a procedure – has the type IO (), "computing" the dummy value ().When a programmer binds an IO value to a function, the function makes decisions based on that view of the world (input from users, files, etc.), then yields a monadic value reflecting the new world-state (program output).[21]

For example, Haskell has several functions for acting on the wider fayl tizimi, including one that checks whether a file exists and another that deletes a file.Their two type signatures are:

doesFileExist :: FilePath -> IO BoolremoveFile :: FilePath -> IO ()

The first is interested in whether a given file really exists, and as a result, outputs a Boolean value ichida IO monad.The second function, on the other hand, is only concerned with acting on the file system so the IO container it outputs is empty.

IO is not limited just to file I/O though; it even allows for user I/O, and along with imperative syntax sugar, can mimic a typical "Salom Dunyo!" dastur:

asosiy :: IO ()asosiy = qil  putStrLn "Salom Dunyo!"  putStrLn "What is your name, user?"  ism <- getLine  putStrLn ("Nice to meet you, " ++ ism ++ "!")

Desugared, this translates into the following monadic pipeline (>> in Haskell is just a variant of bog'lash for when only monadic effects matter and the underlying result can be discarded):

asosiy :: IO ()asosiy =  putStrLn "Salom Dunyo!" >>  putStrLn "What is your name, user?" >>   getLine >>= (\ism ->    putStrLn ("Nice to meet you, " ++ ism ++ "!"))

Writer monad (JavaScript)

Another common situation is keeping a log file or otherwise reporting a program's progress.Sometimes, a programmer may want to log even more specific, technical data for later profil yaratish yoki disk raskadrovka.The Writer monad can handle these tasks by generating auxiliary output that accumulates step-by-step.

To show how the monad pattern is not restricted to primarily functional languages, this example implements a Yozuvchi monad in JavaScript.First, an array (with nested tails) allows constructing the Yozuvchi type as a bog'langan ro'yxat.The underlying output value will live in position 0 of the array, and position 1 will implicitly hold a chain of auxiliary notes:

konst yozuvchi = [qiymat, []];

Ta'riflash birlik is also very simple:

konst birlik = qiymat => [qiymat, []];

Faqat birlik is needed to define simple functions that output Yozuvchi objects with debugging notes:

konst kvadrat shaklida = x => [x * x, [`${x} was squared.`]];konst yarimga qisqardi = x => [x / 2, [`${x} was halved.`]];

A true monad still requires bog'lash, but for Yozuvchi, this amounts simply to appending a function's output to the monad's linked list:

konst bog'lash = (yozuvchi, o'zgartirish) => {    konst [qiymat, jurnal] = yozuvchi;    konst [natija, updates] = o'zgartirish(qiymat);    qaytish [natija, jurnal.concat(updates)];};

The sample functions can now be chained together using bog'lash, but defining a version of monadic composition (called pipelog here) allows applying these functions even more succinctly:

konst pipelog = (yozuvchi, ...transforms) =>    transforms.kamaytirish(bog'lash, yozuvchi);

The final result is a clean separation of concerns between stepping through computations and logging them to audit later:

pipelog(birlik(4), kvadrat shaklida, yarimga qisqardi);// Resulting writer object = [8, ['4 was squared.', '16 was halved.']]

Environment monad

An environment monad (also called a reader monad va a function monad) allows a computation to depend on values from a shared environment. The monad type constructor maps a type T to functions of type ET, qayerda E is the type of the shared environment. The monad functions are:

The following monadic operations are useful:

The so'rang operation is used to retrieve the current context, while mahalliy executes a computation in a modified subcontext. As in a state monad, computations in the environment monad may be invoked by simply providing an environment value and applying it to an instance of the monad.

Formally, a value in an environment monad is equivalent to a function with an additional, anonymous argument; qaytish va bog'lash ga teng K va S combinators, respectively, in the SKI kombinatorini hisoblash.

State monads

A state monad allows a programmer to attach state information of any type to a calculation. Given any value type, the corresponding type in the state monad is a function which accepts a state, then outputs a new state (of type s) along with a return value (of type t). This is similar to an environment monad, except that it also returns a new state, and thus allows modeling a mutable atrof-muhit.

turi Shtat s t = s -> (t, s)

Note that this monad takes a type parameter, the type of the state information. The monad operations are defined as follows:

-- "return" produces the given value without changing the state.qaytish x = \s -> (x, s)-- "bind" modifies m so that it applies f to its result.m >>= f = \r -> ruxsat bering (x, s) = m r yilda (f x) s

Useful state operations include:

olish = \s -> (s, s) -- Examine the state at this point in the computation.qo'yish s = \_ -> ((), s) -- Replace the state.o'zgartirish f = \s -> ((), f s) -- Update the state

Another operation applies a state monad to a given initial state:

runState :: Shtat s a -> s -> (a, s)runState t s = t s

do-blocks in a state monad are sequences of operations that can examine and update the state data.

Informally, a state monad of state type S maps the type of return values T tipdagi funktsiyalarga , qayerda S is the underlying state. The qaytish va bog'lash function are:

.

From the category theory point of view, a state monad is derived from the adjunction between the product functor and the exponential functor, which exists in any kartezian yopiq toifasi ta'rifi bo'yicha.

Continuation monad

A davomi monad with return type R maps type T tipdagi funktsiyalarga . It is used to model davom ettirish uslubi. The return and bind functions are as follows:

The call-with-current-continuation function is defined as follows:

Program logging

The following code is pseudocode. Suppose we have two functions foo va bar, with types

foo : int -> intbar : int -> int

That is, both functions take in an integer and return another integer. Then we can apply the functions in succession like so:

foo (bar x)

Where the result is the result of foo applied to the result of bar ga murojaat qilgan x.

But suppose we are debugging our program, and we would like to add logging messages to foo va bar.So we change the types as so:

foo : int -> int * mag'lubiyatbar : int -> int * mag'lubiyat

So that both functions return a tuple, with the result of the application as the integer, and a logging message with information about the applied function and all the previously applied functions as the string.

Unfortunately, this means we can no longer compose foo va bar, as their input type int is not compatible with their output type int * string. And although we can again gain composablility by modifying the types of each function to be int * string -> int * string, this would require us to add boilerplate code to each function to extract the integer from the tuple, which would get tedious as the number of such functions increases.

Instead, let us define a helper function to abstract away this boilerplate for us:

bog'lash : int * mag'lubiyat -> (int -> int * mag'lubiyat) -> int * mag'lubiyat

bog'lash takes in an integer and string tuple, then takes in a function (like foo) that maps from an integer to an integer and string tuple. Its output is an integer and string tuple, which is the result of applying the input function to the integer within the input integer and string tuple. In this way, we only need to write boilerplate code to extract the integer from the tuple once, in bog'lash.

Now we have regained some composability. Masalan:

bog'lash (bog'lash (x,s) bar) foo

Qaerda (x,s) is an integer and string tuple.

To make the benefits even clearer, let us define an infix operator as an alias for bog'lash:

(>>=) : int * mag'lubiyat -> (int -> int * mag'lubiyat) -> int * mag'lubiyat

Shuning uchun; ... uchun; ... natijasida t >>= f bilan bir xil bind t f.

Then the above example becomes:

((x,s) >>= bar) >>= foo

Finally, it would be nice to not have to write (x, "") every time we wish to create an empty logging message, where "" is the empty string.So let us define a new function:

qaytish : int -> int * mag'lubiyat

Which wraps x in the tuple described above.

Now we have a nice pipeline for logging messages:

((qaytish x) >>= bar) >>= foo

That allows us to more easily log the effects of bar va foo kuni x.

int * string ga o'xshash monadic value. bog'lash va qaytish are analogous to the corresponding functions of the same name.In fact, int * string, bog'lashva qaytish form a monad.

Shuningdek qarang

Alternatives for modeling computations:

Related design concepts:

  • Aspektga yo'naltirilgan dasturlash emphasizes separating out ancillary bookkeeping code to improve modularity and simplicity
  • Tekshirish inversiyasi is the abstract principle of calling specific functions from an overarching framework
  • Sinflarni yozing are a specific language feature used to implement monads and other structures in Haskell
  • The dekorativ naqsh is a more concrete, ad-hoc way to achieve similar benefits in object-oriented programming

Generalizations of monads:

  • Applicative functors generalize from monads by keeping only birlik and laws relating it to xarita
  • Oklar use additional structure to bring plain functions and monads under a single interface
  • Monad transformatorlari act on distinct monads to combine them modularly

Izohlar

  1. ^ Due to the fact that functions on multiple free variables are common in programming, monads as described in this article are technically what category theorists would call strong monads.[3]
  2. ^ Semantik jihatdan M is not trivial and represents an endofunktor ustidan toifasi of all well-typed values:
  3. ^ While a (parametrically polymorphic) function in programming terms, birlik (tez-tez chaqiriladi η in category theory) is mathematically a tabiiy o'zgarish, which maps between funktsiyalar:
  4. ^ bog'lash, on the other hand, is not a natural transformation in category theory, but rather an extension bu ko'targichlar a mapping (from values to computations) into a morphism between computations:
  5. ^ To'liq aytganda, bog'lash may not be formally associative in all contexts because it corresponds to application within lambda hisobi, not mathematics. In rigorous lambda-calculus, evaluating a bog'lash may require first wrapping the right term (when binding two monadic values) or the bind itself (between two monadic functions) in an noma'lum funktsiya to still accept input from the left.[8]
  6. ^ Some languages like Haskell even provide a pseudonym for xarita in other contexts called ko'tarish, along with multiple versions for different parameter counts, a detail ignored here.
  7. ^ Algebraically, the relationship between the two (non-commutative) monoid aspects resembles that of a near-semiring, and some additive monads do qualify as such. However, not all additive monads meet the tarqatuvchi laws of even a near-semiring.[28]
  8. ^ In Haskell, extend is actually defined with the inputs swapped, but as currying is not used in this article, it is defined here as the exact dual of bog'lash.
  9. ^ In category theory, the Shaxsiyat monad can also be viewed as emerging from adjunction of any functor with its inverse.
  10. ^ Category theory views these collection monads as adjunctions between the free functor and different functors from the to'plamlar toifasi uchun category of monoids.

Adabiyotlar

  1. ^ a b v d e f g h O'Sullivan, Bryan; Gersen, Jon; Stewart, Don (2009). "Monads". Real World Haskell. Sebastopol, Kaliforniya: O'Reilly Media. 14-bob. ISBN  978-0596514983.
  2. ^ a b Vadler, Filipp (1990 yil iyun). Monadlarni anglash. ACM Conference on LISP and Functional Programming. Qanchadan-qancha, Frantsiya. CiteSeerX  10.1.1.33.5381.
  3. ^ a b v Moggi, Evgenio (1991). "Hisoblash tushunchalari va monadalar" (PDF). Axborot va hisoblash. 93 (1): 55–92. CiteSeerX  10.1.1.158.5275. doi:10.1016/0890-5401(91)90052-4.
  4. ^ a b v d e Vadler, Filipp (1992 yil yanvar). The essence of functional programming. 19th Annual ACM Symposium on Principles of Programming Languages. Albukerke, Nyu-Meksiko. CiteSeerX  10.1.1.38.9516.
  5. ^ a b Hudak, Paul; Peterson, John; Fasel, Joseph (1999). "About Monads". A Gentle Introduction to Haskell 98. 9-bob.
  6. ^ C. A. McCann's answer (Jul 23 '10 at 23:39) How and why does the Haskell Cont monad work?
  7. ^ Spivey, Mike (1990). "A functional theory of exceptions" (PDF). Kompyuter dasturlash fanlari. 14 (1): 25–42. doi:10.1016/0167-6423(90)90056-J.
  8. ^ "Monad laws". HaskellWiki. haskell.org. Olingan 14 oktyabr 2018.
  9. ^ "What a Monad is not". 7 oktyabr 2018 yil.
  10. ^ De Meuter, Wolfgang (1997). Monads as a theoretical foundation for AOP (PDF). International Workshop on Aspect Oriented Programming at ECOOP. Jyväskylä, Finland. CiteSeerX  10.1.1.25.8262.
  11. ^ "Monad (sans metaphors)". HaskellWiki. 2009 yil 1-noyabr. Olingan 24 oktyabr 2018.
  12. ^ O'Sullivan, Bryan; Gersen, Jon; Stewart, Don (2009). "Using Parsec". Real World Haskell. Sebastopol, Kaliforniya: O'Reilly Media. chapter 16. ISBN  978-0596514983.
  13. ^ Stewart, Don (17 May 2007). "Roll Your Own Window Manager: Tracking Focus with a Zipper". Control.Monad.Writer. Arxivlandi asl nusxasidan 2018 yil 20 fevralda. Olingan 19 noyabr 2018.
  14. ^ Benton, Nick (2015). "Categorical Monads and Computer Programming" (PDF). London Mathematical Society Impact150 Stories. 1. Olingan 19 noyabr 2018.
  15. ^ Kiselyov, Olag (2007). "Delimited Continuations in Operating Systems". Modeling and Using Context. Springer Berlin Heidelberg. pages 291--302. ISBN  978-3-540-74255-5.
  16. ^ Meijer, Erik (27 March 2012). "Your Mouse is a Database". ACM navbati. 10 (3). Olingan 19 noyabr 2018.
  17. ^ Iverson, Kenneth (1987 yil sentyabr). "A dictionary of APL". APL Quote Quad. 18 (1): 5–40. doi:10.1145/36983.36984. ISSN  1088-6826. Olingan 19 noyabr 2018.
  18. ^ Kleisli, Heinrich (1965). "Every standard construction is induced by a pair of adjoint functors" (PDF). Amerika matematik jamiyati materiallari. 16 (3): 544–546. doi:10.1090/S0002-9939-1965-0177024-4. Olingan 19 noyabr 2018.
  19. ^ Peter Pepper, ed. (1997 yil noyabr). The Programming Language Opal (Technical report) (5th corrected ed.). Fachbereich Informatik, Technische Universität Berlin. CiteSeerX  10.1.1.40.2748.
  20. ^ Moggi, Evgenio (Iyun 1989). Computational lambda-calculus and monads (PDF). Fourth Annual Symposium on Logic in computer science. Pacific Grove, California. CiteSeerX  10.1.1.26.2787.
  21. ^ a b Peyton Jones, Simon L.; Vadler, Filipp (1993 yil yanvar). Imperative functional programming (PDF). 20th Annual ACM Symposium on Principles of Programming Languages. Charlston, Janubiy Karolina. CiteSeerX  10.1.1.53.2504.
  22. ^ "Applicative functor". HaskellWiki. Haskell.org. 2018 yil 7-may. Arxivlandi asl nusxasidan 2018 yil 30 oktyabrda. Olingan 20 noyabr 2018.
  23. ^ a b Gibbard, Cale (30 December 2011). "Monads as containers". HaskellWiki. Haskell.org. Arxivlandi asl nusxasidan 2017 yil 14 dekabrda. Olingan 20 noyabr 2018.
  24. ^ a b Piponi, Dan (7 August 2006). "You Could Have Invented Monads! (And Maybe You Already Have.)". A Neighborhood of Infinity. Arxivlandi asl nusxasidan 2018 yil 24 oktyabrda. Olingan 16 oktyabr 2018.
  25. ^ "F # hisoblash ifodalari bo'yicha ba'zi tafsilotlar". Olingan 9 oktyabr 2018.
  26. ^ "Do notation considered harmful". HaskellWiki. Olingan 12 oktyabr 2018.
  27. ^ Giles, Brett (12 August 2013). "Lifting". HaskellWiki. Haskell.org. Arxivlandi asl nusxasidan 2018 yil 29 yanvarda. Olingan 25 noyabr 2018.
  28. ^ a b Rivas, Exequiel; Jaskelioff, Mauro; Schrijvers, Tom (July 2015). From monoids to near-semirings: the essence of MonadPlus and Alternative (PDF). 17th International ACM Symposium on Principles and Practice of Declarative Programming. Siena, Italy. CiteSeerX  10.1.1.703.342.
  29. ^ Swierstra, Wouter (2008). "Data types à la carte" (PDF). Functional Pearl. Funktsional dasturlash jurnali. Kembrij universiteti matbuoti. 18 (4): 423–436. CiteSeerX  10.1.1.101.4131. doi:10.1017/s0956796808006758. ISSN  1469-7653.
  30. ^ Kiselyov, Oleg (May 2012). Schrijvers, Tom; Thiemann, Peter (eds.). Iteratees (PDF). International Symposium on Functional and Logic Programming. Kompyuter fanidan ma'ruza matnlari. 7294. Kobe, Japan: Springer-Verlag. 166-181 betlar. doi:10.1007/978-3-642-29822-6_15. ISBN  978-3-642-29822-6.
  31. ^ Uustalu, Tarmo; Vene, Varmo (July 2005). Horváth, Zoltán (ed.). The Essence of Dataflow Programming (PDF). First Summer School, Central European Functional Programming. Kompyuter fanidan ma'ruza matnlari. 4164. Budapest, Hungary: Springer-Verlag. pp. 135–167. CiteSeerX  10.1.1.62.2047. ISBN  978-3-540-46845-5.
  32. ^ Uustalu, Tarmo; Vene, Varmo (June 2008). "Comonadic Notions of Computation". Nazariy kompyuter fanidagi elektron yozuvlar. Elsevier. 203 (5): 263–284. doi:10.1016/j.entcs.2008.05.029. ISSN  1571-0661.
  33. ^ Quvvat, Jon; Watanabe, Hiroshi (May 2002). "Combining a monad and a comonad" (PDF). Nazariy kompyuter fanlari. Elsevier. 280 (1–2): 137–162. CiteSeerX  10.1.1.35.4130. doi:10.1016/s0304-3975(01)00024-x. ISSN  0304-3975.
  34. ^ Gaboardi, Marko; Katsumata, Shin-ya; Orchard, Dominic; Breuvart, Flavien; Uustalu, Tarmo (September 2016). Combining Effects and Coeffects via Grading (PDF). 21st ACM International Conference on Functional Programming. Nara, Japan: Association for Computing Machinery. 476-489 betlar. doi:10.1145/2951913.2951939. ISBN  978-1-4503-4219-3.

Tashqi havolalar

HaskellWiki references:

  • "All About Monads " (originally by Jeff Newbern) — A comprehensive discussion of all the common monads and how they work in Haskell; includes the "mechanized assembly line" analogy.
  • "Typeclassopedia " (originally by Brent Yorgey) — A detailed exposition of how the leading typeclasses in Haskell, including monads, interrelate.

O'quv qo'llanmalari:

Interesting cases: