এফ-বীজগণিত এবং এফ-কোলজেব্রাগগুলি গাণিতিক কাঠামো যা ইন্ডাকটিভ টাইপগুলি (বা পুনরাবৃত্তিমূলক প্রকারগুলি ) সম্পর্কে যুক্তি প্রদানে সহায়ক ।
এফ algebras
আমরা প্রথম এফ-বীজগণিত দিয়ে শুরু করব। আমি যতটা সম্ভব সহজ হওয়ার চেষ্টা করব।
আমি অনুমান করি আপনি জানেন যে একটি পুনরাবৃত্তির ধরন কি। উদাহরণস্বরূপ, এটি পূর্ণসংখ্যার তালিকার জন্য একটি প্রকার:
data IntList = Nil | Cons (Int, IntList)
এটা স্পষ্ট যে এটি পুনরাবৃত্তি - প্রকৃতপক্ষে, এর সংজ্ঞা নিজেকে বোঝায়। এর সংজ্ঞাটিতে দুটি ডেটা কনস্ট্রাক্টর রয়েছে, যার নিম্নলিখিত ধরণের রয়েছে:
Nil :: () -> IntList
Cons :: (Int, IntList) -> IntList
নোট করুন যে আমি প্রকারের Nil
মতো লিখেছি () -> IntList
, সহজভাবে নয় IntList
। এগুলি আসলে তাত্ত্বিক দৃষ্টিকোণ থেকে সমতুল্য ধরণের, কারণ ()
প্রকারের কেবলমাত্র একটি বাসিন্দা রয়েছে।
আমরা যদি আরও নির্ধারিত-তাত্ত্বিক উপায়ে এই ফাংশনগুলির স্বাক্ষরগুলি লিখি, আমরা পেয়ে যাব
Nil :: 1 -> IntList
Cons :: Int × IntList -> IntList
যেখানে 1
ইউনিট সেট (একটি উপাদান সহ সেট) এবং A × B
অপারেশন হ'ল দুটি সেটের ক্রস প্রোডাক্ট A
এবং B
(যা জোড়ার সেট (a, b)
যেখানে a
সমস্ত উপাদানগুলির মধ্য দিয়ে যায় A
এবং b
সমস্ত উপাদানগুলির মধ্য দিয়ে যায় B
)।
দুটি সেটের মিলন বিচ্ছিন্ন করা A
এবং B
এটি এমন একটি সেট A | B
যা সেটগুলির মিল {(a, 1) : a in A}
এবং {(b, 2) : b in B}
। মূলত এটি উভয়ই A
এবং সমস্ত উপাদানগুলির একটি সেট B
, তবে এই উপাদানগুলির প্রত্যেকটির সাথে ' A
বা ' চিহ্নযুক্ত বা হিসাবে চিহ্নিত B
, সুতরাং যখনই আমরা কোনও উপাদান বাছাই করি A | B
আমরা তত্ক্ষণাত বুঝতে পারি যে এই উপাদানটি এসেছে A
বা কোথা থেকে এসেছে B
।
আমরা 'যোগদান' Nil
এবং Cons
ফাংশন করতে পারি , সুতরাং সেগুলি সেটে কাজ করে একটি একক ফাংশন গঠন করবে 1 | (Int × IntList)
:
Nil|Cons :: 1 | (Int × IntList) -> IntList
প্রকৃতপক্ষে, যদি Nil|Cons
ফাংশনটি ()
মানটির সাথে প্রয়োগ করা হয় (যা স্পষ্টতই 1 | (Int × IntList)
সেটটি অন্তর্গত ) তবে এটি এটির মতো আচরণ করে Nil
; যদি Nil|Cons
কোনও ধরণের মান প্রয়োগ করা হয় (Int, IntList)
(যেমন মানগুলি সেটে থাকে তবে 1 | (Int × IntList)
এটি এর মতো আচরণ করে Cons
।
এখন অন্য একটি ডেটাটাইপ বিবেচনা করুন:
data IntTree = Leaf Int | Branch (IntTree, IntTree)
এটিতে নিম্নলিখিত নির্মাণকারী রয়েছে:
Leaf :: Int -> IntTree
Branch :: (IntTree, IntTree) -> IntTree
যা একটি ফাংশনে যোগ দিতে পারে:
Leaf|Branch :: Int | (IntTree × IntTree) -> IntTree
এটি দেখা যায় যে এই joined
ফাংশনগুলির উভয়েরই একই ধরণের রয়েছে: তারা উভয়ই দেখতে দেখতে একই রকম
f :: F T -> T
যেখানে F
এক ধরণের রূপান্তর হয় যা আমাদের ধরণের লাগে এবং আরও জটিল ধরণের দেয়, যা গঠিত x
এবং |
পরিচালনা করে, T
সম্ভবত অন্যান্য ধরণের ব্যবহার এবং ব্যবহার করে । উদাহরণস্বরূপ, নিম্নলিখিত হিসাবে দেখায় IntList
এবং IntTree
F
দেখায়:
F1 T = 1 | (Int × T)
F2 T = Int | (T × T)
আমরা তাত্ক্ষণিকভাবে লক্ষ্য করতে পারি যে কোনও বীজগণিতের ধরণ এভাবে লেখা যায়। প্রকৃতপক্ষে, এ কারণেই তাদের 'বীজগণিত' বলা হয়: এগুলি বিভিন্ন ধরণের 'যোগস' (ইউনিয়ন) এবং 'পণ্য' (ক্রস পণ্য) নিয়ে থাকে।
এখন আমরা এফ-বীজগণিত সংজ্ঞায়িত করতে পারি। এফ-বীজগণিতটি কেবল একটি জোড়া (T, f)
, যেখানে T
কিছু প্রকার এবং f
এটি একটি ফাংশন f :: F T -> T
। আমাদের উদাহরণগুলিতে এফ-বীজগণিতগুলি হ'ল (IntList, Nil|Cons)
এবং (IntTree, Leaf|Branch)
। তবে নোট করুন, যদিও এই ধরণের f
ক্রিয়াটি প্রতিটি এফের জন্য একই T
এবং f
এগুলি স্বেচ্ছাসেবী হতে পারে। উদাহরণস্বরূপ, (String, g :: 1 | (Int x String) -> String)
বা (Double, h :: Int | (Double, Double) -> Double)
কিছু জন্য g
এবং h
রয়েছে সংশ্লিষ্ট এফ জন্য এফ algebras
এরপরে আমরা এফ-বীজগণিত হোমোর্ফিজমগুলি এবং তারপরে প্রাথমিক এফ-বীজগণিতগুলি প্রবর্তন করতে পারি , যার খুব দরকারী বৈশিষ্ট্য রয়েছে। আসলে (IntList, Nil|Cons)
এটি প্রাথমিক এফ 1-বীজগণিত, এবং (IntTree, Leaf|Branch)
এটি প্রাথমিক এফ 2-বীজগণিত। আমি এই শর্তাদি এবং বৈশিষ্ট্যগুলির সঠিক সংজ্ঞা উপস্থাপন করব না কারণ সেগুলি প্রয়োজনের চেয়ে আরও জটিল এবং বিমূর্ত।
তবুও, সত্য যে, বলুন, (IntList, Nil|Cons)
এফ-বীজগণিত আমাদের fold
এই ধরণের উপর পছন্দ মত ফাংশন সংজ্ঞায়িত করতে দেয় । আপনি জানেন যে, ভাঁজ এক ধরণের অপারেশন যা কিছু সীমাবদ্ধ মানটিতে একটি পুনরাবৃত্ত ডাটাটাইপকে রূপান্তর করে। উদাহরণস্বরূপ, আমরা পূর্ণসংখ্যার একটি তালিকাকে একক মানতে ফোল্ড করতে পারি যা তালিকার সমস্ত উপাদানগুলির যোগফল:
foldr (+) 0 [1, 2, 3, 4] -> 1 + 2 + 3 + 4 = 10
যে কোনও পুনরাবৃত্তির ডেটাটাইপতে এ জাতীয় অপারেশনটিকে সাধারণকরণ করা সম্ভব।
নিম্নলিখিত foldr
ফাংশনের স্বাক্ষর :
foldr :: ((a -> b -> b), b) -> [a] -> b
নোট করুন যে আমি গত দুটি থেকে প্রথম দুটি যুক্তি পৃথক করতে ব্রেস ব্যবহার করেছি। এটি আসল foldr
ফাংশন নয়, তবে এটি এর কাছে আইসোমরফিক (এটি হ'ল আপনি সহজেই অন্যের কাছ থেকে একটি পেতে পারেন এবং বিপরীতে)। আংশিক প্রয়োগের foldr
জন্য নিম্নলিখিত স্বাক্ষর থাকবে:
foldr ((+), 0) :: [Int] -> Int
আমরা দেখতে পাচ্ছি যে এটি একটি ফাংশন যা পূর্ণসংখ্যার একটি তালিকা নেয় এবং একটি একক পূর্ণসংখ্যা ফেরত দেয়। আসুন আমাদের IntList
ধরণের ক্ষেত্রে এই জাতীয় ফাংশন সংজ্ঞায়িত করা যাক ।
sumFold :: IntList -> Int
sumFold Nil = 0
sumFold (Cons x xs) = x + sumFold xs
আমরা দেখি এই ফাংশন দুটি অংশ নিয়ে গঠিত যে: প্রথম পক্ষ থেকে এই ফাংশন আচরণ সংজ্ঞায়িত Nil
অংশ IntList
, এবং দ্বিতীয় পক্ষ থেকে ফাংশনের আচরণ সংজ্ঞায়িত Cons
অংশ।
এখন ধরা যাক আমরা হাস্কেল নয় বরং এমন কিছু ভাষায় প্রোগ্রাম করছি যা বীজগণিতের ধরণের প্রত্যক্ষ স্বাক্ষরগুলিতে সরাসরি ব্যবহারের অনুমতি দেয় (ভাল, প্রযুক্তিগতভাবে হাস্কেল টিউপলস এবং Either a b
ডেটাটাইপের মাধ্যমে বীজগণিতের ধরণের ব্যবহারের অনুমতি দেয় , তবে এটি অপ্রয়োজনীয় ভার্বোসিতির দিকে পরিচালিত করবে)। একটি ফাংশন বিবেচনা করুন:
reductor :: () | (Int × Int) -> Int
reductor () = 0
reductor (x, s) = x + s
এটি দেখা যায় যে এফ-বীজগণিতের সংজ্ঞা অনুসারে, এটি reductor
টাইপের একটি ফাংশন F1 Int -> Int
! আসলে, এই জুটি (Int, reductor)
একটি F1-বীজগণিত bra
কারণ IntList
একটি প্রাথমিক এফ 1-বীজগণিত, প্রতিটি প্রকারের T
জন্য এবং প্রতিটি ফাংশনের জন্য r :: F1 T -> T
একটি ফাংশন রয়েছে, যার জন্য ক্যাটামোর্ফিজম নামে পরিচিত r
, যা রূপান্তরিত IntList
হয় T
এবং এই জাতীয় ক্রিয়াটি অনন্য। প্রকৃতপক্ষে, আমাদের উদাহরণে একটি catamorphism reductor
হয় sumFold
। কিভাবে reductor
এবং sumFold
অনুরূপ নোট করুন : তাদের প্রায় একই কাঠামো আছে! ইন reductor
সংজ্ঞা s
প্যারামিটার ব্যবহার (টাইপ যার অনুরূপ T
এর গণনার ফল ব্যবহারের সাথে সঙ্গতিপূর্ণ) sumFold xs
মধ্যে sumFold
সংজ্ঞা।
এটি আরও স্পষ্ট করতে এবং প্যাটার্নটি দেখতে আপনাকে সহায়তা করার জন্য, এখানে আরও একটি উদাহরণ রয়েছে এবং আমরা আবার ফলস্বরূপ ভাঁজ ফাংশনটি থেকে শুরু করি। append
ফাংশনটি বিবেচনা করুন যা এটির প্রথম যুক্তিকে দ্বিতীয়টির সাথে যুক্ত করে:
(append [4, 5, 6]) [1, 2, 3] = (foldr (:) [4, 5, 6]) [1, 2, 3] -> [1, 2, 3, 4, 5, 6]
এটি আমাদের দেখতে কেমন IntList
:
appendFold :: IntList -> IntList -> IntList
appendFold ys () = ys
appendFold ys (Cons x xs) = x : appendFold ys xs
আবার, রিডাক্টরটি লেখার চেষ্টা করি:
appendReductor :: IntList -> () | (Int × IntList) -> IntList
appendReductor ys () = ys
appendReductor ys (x, rs) = x : rs
appendFold
appendReductor
রূপান্তর IntList
হয় যার জন্য রূপান্তরিত হয় IntList
।
সুতরাং, মূলত, এফ-বীজগণিতগুলি আমাদের পুনরাবৃত্তির উপাত্তাস্ত্রগুলিতে 'ভাঁজ' সংজ্ঞায়িত করার অনুমতি দেয়, অর্থাত্ যে ক্রিয়াকলাপগুলি আমাদের কাঠামোগুলিকে কিছুটা মূল্য হ্রাস করে।
এফ coalgebras
এফ-কয়লাজেব্রাসগুলি এফ-বীজগণিতগুলির জন্য তথাকথিত 'দ্বৈত' শব্দ। তারা আমাদের unfolds
পুনরাবৃত্তির ডেটাটাইপগুলির জন্য সংজ্ঞা দিতে দেয় , এটি হ'ল কিছু মান থেকে রিকার্সিভ স্ট্রাকচার তৈরির উপায়।
ধরুন আপনার নিম্নলিখিত ধরণের রয়েছে:
data IntStream = Cons (Int, IntStream)
এটি পূর্ণসংখ্যার এক অসীম প্রবাহ। এর একমাত্র নির্মাতার নিম্নলিখিত ধরণের রয়েছে:
Cons :: (Int, IntStream) -> IntStream
অথবা, সেটের ক্ষেত্রে
Cons :: Int × IntStream -> IntStream
হাস্কেল আপনাকে ডেটা কনস্ট্রাক্টরের সাথে প্যাটার্ন ম্যাচ করার অনুমতি দেয়, যাতে আপনি নিম্নলিখিত ফাংশনগুলিকে এস এ কাজ করতে পারেন IntStream
:
head :: IntStream -> Int
head (Cons (x, xs)) = x
tail :: IntStream -> IntStream
tail (Cons (x, xs)) = xs
আপনি স্বাভাবিকভাবে এই ফাংশনগুলিকে টাইপের একক ফাংশনে 'যোগদান' করতে পারেন IntStream -> Int × IntStream
:
head&tail :: IntStream -> Int × IntStream
head&tail (Cons (x, xs)) = (x, xs)
লক্ষ্য করুন কীভাবে ফাংশনের ফলাফলটি আমাদের IntStream
ধরণের বীজগণিত উপস্থাপনার সাথে মিলে যায় । অন্যান্য পুনরাবৃত্ত ডেটা ধরণের ক্ষেত্রেও একই জিনিস করা যেতে পারে। হতে পারে আপনি ইতিমধ্যে প্যাটার্নটি লক্ষ্য করেছেন। আমি টাইপ ফাংশন একটি পরিবার উল্লেখ করছি
g :: T -> F T
যেখানে T
কিছু ধরণের। এখন থেকে আমরা সংজ্ঞায়িত করব
F1 T = Int × T
এখন, এফ-কয়লাজেব্রা একটি জুড়ি (T, g)
, যেখানে T
এক ধরণের এবং g
টাইপের ফাংশন g :: T -> F T
। উদাহরণস্বরূপ, (IntStream, head&tail)
একটি এফ 1-কয়লাজেব্রা। আবার, ঠিক যেমন এফ-বীজগণিতগুলিতে, g
এবং T
যথেচ্ছ হতে পারে, উদাহরণস্বরূপ, (String, h :: String -> Int x String)
কিছু এইচ এর জন্য এফ 1-কয়লাজেব্রাও।
সমস্ত এফ-কয়লাজেব্রাগুলির মধ্যে তথাকথিত টার্মিনাল এফ-কয়লাজেব্রা রয়েছে , যা প্রাথমিক এফ-বীজগণিতগুলির দ্বৈত। উদাহরণস্বরূপ, IntStream
একটি টার্মিনাল এফ-কয়লাজেব্রা। এর অর্থ হ'ল প্রতিটি ধরণের T
জন্য এবং প্রতিটি ফাংশনের জন্য p :: T -> F1 T
একটি ফাংশন রয়েছে যার নাম অ্যানামরফিজম , যা রূপান্তর T
করে IntStream
, এবং এই জাতীয় ফাংশনটি অনন্য।
নিম্নলিখিত ফাংশনটি বিবেচনা করুন, যা প্রদত্ত একটি থেকে শুরু করে ধারাবাহিক পূর্ণসংখ্যার একটি স্ট্রিম উত্পন্ন করে:
nats :: Int -> IntStream
nats n = Cons (n, nats (n+1))
এখন একটি ফাংশন পরিদর্শন দিন natsBuilder :: Int -> F1 Int
, যে, natsBuilder :: Int -> Int × Int
:
natsBuilder :: Int -> Int × Int
natsBuilder n = (n, n+1)
আবার, আমরা nats
এবং এর মধ্যে কিছু মিল খুঁজে পেতে পারি natsBuilder
। এটি আমরা সংযোগের সাথে খুব কমই এর আগে একই সাথে রিডাক্টর এবং ভাঁজগুলির সাথে পর্যবেক্ষণ করেছি। nats
জন্য anamorphism হয় natsBuilder
।
আর একটি উদাহরণ, একটি ফাংশন যা একটি মান এবং একটি ফাংশন নেয় এবং ফাংশনের ক্রমাগত প্রয়োগগুলির একটি স্ট্রিমকে মানটিতে ফেরত দেয়:
iterate :: (Int -> Int) -> Int -> IntStream
iterate f n = Cons (n, iterate f (f n))
এর বিল্ডার ফাংশনটি নিম্নলিখিত একটি:
iterateBuilder :: (Int -> Int) -> Int -> Int × Int
iterateBuilder f n = (n, f n)
তারপরে iterate
এটি একটি অ্যানোরমিজম iterateBuilder
।
উপসংহার
সুতরাং, সংক্ষেপে, এফ-বীজগণিতগুলি ভাঁজগুলি সংজ্ঞায়িত করার অনুমতি দেয়, অর্থাৎ অপারেশনগুলি যা পুনরাবৃত্ত কাঠামোকে একটি একক মানের মধ্যে হ্রাস করে এবং এফ-কয়লাজেব্রারা বিপরীতে এটি করতে দেয়: একক মান থেকে একটি [সম্ভাব্য] অসীম কাঠামো তৈরি করে।
আসলে হাস্কেল এফ-বীজগণিত এবং এফ-কয়লাজেব্রাসের সাথে মিল রয়েছে। এটি একটি খুব সুন্দর সম্পত্তি যা প্রতিটি ধরণের 'নীচে' মান উপস্থিতির ফলাফল। সুতরাং হাস্কেলগুলিতে প্রতিটি পুনরাবৃত্ত প্রকারের জন্য দুটি ভাঁজ এবং অনাবৃত তৈরি করা যেতে পারে। যাইহোক, এর পিছনে তাত্ত্বিক মডেল আমি উপরে উপস্থাপনের চেয়ে জটিল, তাই আমি ইচ্ছাকৃতভাবে এড়াতে পেরেছি।
আশাকরি এটা সাহায্য করবে.