Haskellda funktorlar - Tiplarni dinamik tarzda

Haskellda funktorlar. Haskelldagi funktorlar haqiqiy funktorlar bo‘lishi bilan farqlanadi. Haskelldagi funktorlar kategoriya nazariyasidan matematik funktorlarga juda o‘xshaydi (Kategoriya nazariyasi-matematikaning obʻyektlarning ichki tuzilishiga bog‘liq bo‘lmagan matematik obʻyektlar o‘rtasidagi munosabatlarning xususiyatlarini o‘rganadigan bo‘limi). Kategoriya nazariyasida funktor F kategoriyalar o‘rtasida shunday taqsimlanishi kerakki, kategoriya strukturasi saqlanib qolsin yoki boshqacha qilib aytganda, u ikki kategoriya orasidagi gomomorfizm bo‘lsin.
Bu taʻrif Haskellda oddiy tipdagi sinf sifatida amalga oshiriladi.
class Functor f where
fmap :: (a -> b) -> f a -> f b
|
ML ga qarab, masalan, Haskell tipi plagin sinfiga o‘xshaydi, joriy Sinfning nusxasi bo‘lish uchun qaysi amallarni qanday qilib yaratishni aniqlaydi. Bu holatda, birgina Functor tiplar bo‘yicha aniqlanmagan, balki f konstruktor asosida aniqlangan. Bundan shuni bilish mumkinki Functor – fmap funksiyasini yaratib beradi. fmap funksiyasi a tipini qabul qiladi va b tipini qaytaradi. fa (f konstruktori
asosida qurilgan tip, a ga qo‘llaniladi) qabul qilinadigan tip va fb qaytariladigan tip.
Uni tushunish uchun, baʻzi konreynerda har bir element uchun amal qiladigan funksiyasi sifatida fmap funksiyasini o‘ylab ko‘ring. Funktorlarning eng oddiy misoli muntazam ro‘yxatlar va map funksiyasi bo‘lib, u ro‘yxatdagi har bir element uchun funksiyani qo‘llaydi.
Prelude> map (+1) [1,2,3,4,5]
[2,3,4,5,6]
|
Bu oddiy misolda fmap funksiyasi faqat map va f tipidagi konstruktor [] - list tipidagi konstruktordir. Shuning uchun, ro‘yxatlar uchun, masalan, Functor sifatida belgilangan.
instance Functor [] where
fmap = map
|
Bu map o‘rniga fmap yordamida fragmentni shakllantirib olsak, albatta, to‘g‘ri bo‘ldi.
Prelude> fmap (+1) [1,2,3,4,5]
[2,3,4,5,6]
|
Lekin funktor taʻrifi tuzilishini asrab-avaylash haqida hech narsa demaydi, unutmang! Shuning uchun har qanday normal funktorlar matematik funksiyalar taʻrifiga kiruvchi funktorlar qonunlarini qanoatlantirishi kerak. Fmapning ikki qoidalari bor:
fmap id = id
fmap (g. h) = fmap g. fmap h
|
Birinchi qoidada konteynerda har bir element uchun bir xil funksiyani xaritalash hech qanday taʻsiri yo‘q deb aytilgan. Ikkinchi qoidaga ko‘ra, konteynerdagi har bir element ustida ikkita funksiyaning tarkibi birinchi funksiyani ko‘rsatish bilan, so‘ngra ikkinchisini ko‘rsatish bilan bir xil bo‘ladi.
Ularni yaqqol ko‘rsatish uchun funktorlarga yana bir misol daraxtlar ustida amallar hisoblanadi. Bir konteyner sifatida daraxt, shajara (ierarxiya, ichma ich joylashgan obʻyektlar) berilgan bo‘lsin. Daraxt tuzilishini saqlab qolish uchun, daraxt xususityalariga fmap funksiyasini qo‘llaymiz. Buning uchun birinchi daraxtni belgilab boshlaymiz.
data Tree a = Node (Tree a) (Tree a)
| Leaf a deriving Show
|
Bu fragmentda daraxt turi ikki daraxtning (chap va o‘ng tugunlaruga) tuguni (node) yoki barg (leaf) ekanligi aytiladi. deriving Show ifodasi show funksiyasi orqali ko‘rish imkonini beradi. Endi Tree daraxti ustida funktorni aniqlay olamiz.
instance Functor Tree where fmap g (Leaf v) = Leaf (g v)
fmap g (Node l r) = Node (fmap g l) (fmap g r)
|
Bu fragmentda fmap tipidagi g funksiyasi argumuent sifatida Leaf tipli v qiymatni qabul qiladi va Leaf tipidagi gni vga qiymat qilib beradi. Ikkinchi qoidada fmap tipiga oid g funksiyasi Node tipidagi l va r qiymatlarni qabul qiladi va natijada Node funksiyasi fmap tipidagi gl va gr argumentlarni qiymat qilib beradi.
Fmap funksiyasini tree obʻyektlari bilan ishlash uchun tayyorlaymiz. Tree sinfni satrli (string) ro‘yxat bilan quramiz va har bir ro‘yxat uzunligini length()funksiyasi bilan aniqlaymiz.
Prelude> let tree = (Node (Node (Leaf “c21”) (Leaf “cate22”) (Leaf “categoty11”)) Prelude> fmap length tree
Node (Node (Leaf 3) (Leaf 6)) (Leaf 10)
|
Quyidagicha tree quriladi:
(b)
4.1-rasm. (a) tree ko‘rinishi, (b) length() bo‘yicha ko‘rinishi.
Aslida, Haskell da funktorlar fundamental funktor sinfi hisoblanadi va applicative functors va strelkalar barchasi bular ham funktorlaridir. Haskell funksiyalar murakkab hisoblanadi, agar bu funktorlarni haqiqiy xayot qonuniyatlari bag‘lab o‘rganmoqchi bo‘lsangi, alohida fan va manbalarni o‘rganish lozim.
Prolog funktorlari. Bu hammasidan oson funktorlardir. Ikkita misol qaraymiz. Birinchisi atom - bu tuzilmaning birinchisidir. Ifodani qaraymiz:
Birinchi atom funktordir – likes
Ikkinchisi- functor deb nomlangan ajralmas predmet. Bu argumentlari va funktor tuzilmasini qaytaradi. masalan,
?- functor(likes(olma, nok), Functor, Arity). Functor = likes
Arity = 2
|
Bu Prolog funktorlarga misol edi.
Funktorlarni yaratish dasturchilarga xos emas albatta. Chunki bugungi kunda tayyor foydalanish uchun ko‘plab funktorlar yaratilgan. Ularni asosan instrument yaratuvchilar, yaʻni dasturchilar uchun dastur tuzuvchilar yaratadi ap mantiqiy dasturlash funktorlarning o‘rni muhim ahamiyat kasb etadi.
|