দুঃখিত, আমি সত্যিই আমার গণিত জানি না, তাই আমি আবেদনকারী টাইপক্লাসে কীভাবে ফাংশনগুলি উচ্চারণ করতে পারি তা আগ্রহী
আমি মনে করি আপনার গণিতটি জানা বা না জানা এখানে মূলত অপ্রাসঙ্গিক। আপনি সম্ভবত অবহিত হিসাবে, হাস্কেল বিমূর্ত গণিতের বিভিন্ন ক্ষেত্র, বিশেষত বিভাগ তত্ত্ব থেকে কিছু সংখ্যক বিট ধার নিয়েছেন , যেখান থেকে আমরা ফান্টেক্টর এবং ম্যানড পাই। হাস্কেলের এই পদগুলির ব্যবহার আনুষ্ঠানিক গাণিতিক সংজ্ঞা থেকে কিছুটা আলাদা হয়ে যায় তবে এগুলি সাধারণত ভাল বর্ণনামূলক শর্ত হিসাবে যথেষ্ট পর্যায়ে রয়েছে।
Applicative
টাইপ শ্রেণীর মধ্যে কোথাও বসে Functor
এবং Monad
, তাই এক এটি একটি অনুরূপ গাণিতিক ভিত্তি আছে আশা করবে। Control.Applicative
মডিউলটির জন্য ডকুমেন্টেশন এর সাথে শুরু হয়:
এই মডিউলটি একটি ফান্টেক্টর এবং একটি মনাডের মধ্যে একটি কাঠামো মধ্যবর্তীটিকে বর্ণনা করে: এটি খাঁটি অভিব্যক্তি এবং সিকোয়েন্সিং সরবরাহ করে, তবে কোনও বাঁধাই করে না। (প্রযুক্তিগতভাবে, একটি শক্তিশালী শিথিল মনোফিডাল ফ্যাক্টর।)
হুম।
class (Functor f) => StrongLaxMonoidalFunctor f where
. . .
Monad
আমার মতো মনে হয় না তেমন আকর্ষণীয় ।
মূলত এই সমস্ত কিসের উত্সাহ তা হ'ল এটি Applicative
কোনও গাণিতিকভাবে বিশেষভাবে আকর্ষণীয় কোনও ধারণার সাথে মিলে না , সুতরাং হাস্কেলের ব্যবহারের উপায়ে ক্যাপচার কোনও শর্ত নেই around সুতরাং, আপাতত গণিতটি আলাদা করুন।
আমরা কী বলতে চাই তা জানতে চাইলে (<*>)
এটির মূলত অর্থ কী তা জানতে সহায়তা করতে পারে।
তাই কি করে উঠে Applicative
যাই হোক, এবং কেন না আমরা যে কল?
কি Applicative
বাস্তবে পরিমাণ উত্তোলন একটি উপায় নির্বিচারে একটি মধ্যে ফাংশন Functor
। Maybe
(তর্কযোগ্যভাবে সহজতম তুচ্ছ Functor
) এবং Bool
(একইভাবে সরল অ-তুচ্ছ ডেটা টাইপের) সংমিশ্রণটি বিবেচনা করুন ।
maybeNot :: Maybe Bool -> Maybe Bool
maybeNot = fmap not
ফাংশনটি fmap
আমাদের not
কাজ করে কাজ করা Bool
থেকে উঠতে দেয় Maybe Bool
। কিন্তু যদি আমরা উত্তোলন করতে চাই (&&)
?
maybeAnd' :: Maybe Bool -> Maybe (Bool -> Bool)
maybeAnd' = fmap (&&)
ওয়েল, এটা কি আমরা চাই না এ সব ! আসলে, এটি বেশ অযথা। আমরা চালাক হওয়ার চেষ্টা করতে পারি এবং অন্যটিকে পিছনের Bool
দিকে লুকিয়ে দেখতে পারি Maybe
...
maybeAnd'' :: Maybe Bool -> Bool -> Maybe Bool
maybeAnd'' x y = fmap ($ y) (fmap (&&) x)
... তবে এটি ভাল নয়। একটি জিনিস, এটি ভুল। অন্য একটি জিনিস, এটি কদর্য । আমরা চেষ্টা চালিয়ে যেতে পারতাম, তবে দেখা গেছে যে স্বেচ্ছায় কাজ করার জন্য একাধিক যুক্তি ফাংশন তুলতে পারে নাFunctor
। বিরক্তিকর!
অন্যদিকে, আমরা যদি Maybe
এর Monad
উদাহরণ ব্যবহার করি তবে আমরা এটি সহজেই করতে পারতাম :
maybeAnd :: Maybe Bool -> Maybe Bool -> Maybe Bool
maybeAnd x y = do x' <- x
y' <- y
return (x' && y')
এখন, কেবল একটি সাধারণ ফাংশনটি অনুবাদ করার জন্য এটি অনেক ঝামেলা - যার কারণে Control.Monad
এটি কোনও ফাংশন স্বয়ংক্রিয়ভাবে করার জন্য সরবরাহ করে liftM2
। এর নামের ২ টি সত্যটি বোঝায় যে এটি ঠিক দুটি যুক্তির কাজ করে; 3, 4, এবং 5 টি যুক্তি ফাংশনের জন্য অনুরূপ ফাংশন বিদ্যমান। এই ফাংশনগুলি আরও ভাল , তবে নিখুঁত নয় এবং যুক্তিগুলির সংখ্যা উল্লেখ করা কুশ্রী এবং আনাড়ি।
যা আমাদের কাগজে এনে দেয় যা আবেদনকারী ধরণের শ্রেণি চালু করে । এতে লেখকরা মূলত দুটি পর্যবেক্ষণ করেন:
- মাল্টি-আর্গুমেন্ট ফাংশনগুলিকে একটিতে তুলনা করা
Functor
খুব স্বাভাবিক জিনিস thing
- এটি করার জন্য এ এর সম্পূর্ণ ক্ষমতা প্রয়োজন হয় না
Monad
সাধারণ ফাংশন অ্যাপ্লিকেশনটি শর্তগুলির সরল রচনা দ্বারা লিখিত হয়, সুতরাং "উত্তোলিত অ্যাপ্লিকেশন" যথাসম্ভব সহজ এবং প্রাকৃতিক করার জন্য, কাগজটি ইনফিক্স অপারেটরগুলিকে প্রয়োগের জন্য দাঁড় করায়Functor
, উপরের দিকে তুলে নিয়েছে এবং এর জন্য প্রয়োজনীয় কিছুর জন্য একটি টাইপ ক্লাস প্রবর্তন করে ।
এর সবকটিই আমাদের নীচের পয়েন্টে নিয়ে আসে: (<*>)
কেবল ফাংশন অ্যাপ্লিকেশনকে উপস্থাপন করে - তবে কেন আপনি সাদা স্থান "জুস্টস্টেজেশন অপারেটর" এর চেয়ে আলাদাভাবে এটি উচ্চারণ করবেন?
তবে যদি এটি খুব সন্তোষজনক না হয় তবে আমরা পর্যবেক্ষণ করতে পারি যে Control.Monad
মডিউলটি একটি ক্রিয়াও সরবরাহ করে যা মনাদের জন্য একই কাজ করে:
ap :: (Monad m) => m (a -> b) -> m a -> m b
কোথায় ap
"প্রয়োগ" সংক্ষিপ্ত অবশ্যই, হয়। যেহেতু যে কোনও Monad
হতে পারে Applicative
এবং ap
কেবলমাত্র পরবর্তী বৈশিষ্ট্যের উপসেট প্রয়োজন, তাই আমরা সম্ভবত এটি বলতে পারি যে অপারেটর না হলে (<*>)
এটি কল করা উচিত ap
।
আমরা অন্য দিক থেকে জিনিসগুলির কাছেও যেতে পারি। Functor
উত্তোলন অপারেশন বলা হয় fmap
কারণ এটি একটি সাধারণীকরণ এর map
তালিকায় অপারেশন। তালিকাগুলিতে কি ধরণের ফাংশন কাজ করবে (<*>)
? ap
তালিকাগুলিতে অবশ্যই যা আছে তা রয়েছে তবে এটি নিজস্বভাবে বিশেষ কার্যকর নয়।
আসলে, তালিকাগুলির জন্য সম্ভবত আরও একটি প্রাকৃতিক ব্যাখ্যা রয়েছে interpretation আপনি নিম্নলিখিত ধরণের স্বাক্ষরটি দেখলে কী মনে আসে?
listApply :: [a -> b] -> [a] -> [b]
সমান্তরালভাবে তালিকাগুলি রেখাযুক্ত করার ধারণা সম্পর্কে খুব লোভনীয় কিছু রয়েছে যা প্রথমটির প্রতিটি অংশটিকে দ্বিতীয়টির সাথে সম্পর্কিত উপাদানটিতে প্রয়োগ করে। দুর্ভাগ্যক্রমে আমাদের পুরানো বন্ধুর জন্য Monad
, যদি তালিকাগুলি বিভিন্ন দৈর্ঘ্যের হয় তবে এই সাধারণ অপারেশনটি মানড আইন লঙ্ঘন করে । তবে এটি সূক্ষ্ম করে তোলে Applicative
, এক্ষেত্রে একটি সাধারণ সংস্করণ একসাথে স্ট্রিংয়ের(<*>)
একটি উপায় হয়ে যায় , তাই সম্ভবত আমরা এটি কল করার কল্পনা করতে পারি ?zipWith
fzipWith
এই জিপিং ধারণাটি আসলে আমাদের পুরো বৃত্ত নিয়ে আসে। একাদিক ফান্টেক্টর সম্পর্কে, আগে এই গণিতের জিনিসগুলি মনে রাখবেন? নামটি যেমন বোঝায়, এগুলি মনোয়েড এবং ফান্টাক্টরের কাঠামোর সংমিশ্রনের একটি উপায়, যা উভয়ই পরিচিত হাস্কেল টাইপ শ্রেণি:
class Functor f where
fmap :: (a -> b) -> f a -> f b
class Monoid a where
mempty :: a
mappend :: a -> a -> a
আপনি যদি তাদের একটি বাক্সে একসাথে রেখে কিছুটা ঝেড়ে ফেলেন তবে এগুলি দেখতে কেমন হবে? থেকে Functor
আমরা একটি ধারণা করা চালিয়ে যাব এর ধরন প্যারামিটারের গঠন স্বাধীন থেকে, এবং Monoid
আমরা ফাংশন সামগ্রিক ফর্ম যাব:
class (Functor f) => MonoidalFunctor f where
mfEmpty :: f ?
mfAppend :: f ? -> f ? -> f ?
আমরা একটি সত্যিকারের "খালি" তৈরি করার জন্য একটি উপায় আছে যে অনুমান করতে না চান Functor
, এবং আমরা, একটি অবাধ ধরনের একটি মান ভেলকি দেখান আপ করতে পারবেন না তাই আমরা ধরণ ঠিক করব mfEmpty
যেমন f ()
।
আমরা mfAppend
একটি সামঞ্জস্যপূর্ণ টাইপ পরামিতি প্রয়োজন জোর করতে চাই না , সুতরাং এখন আমাদের এটি আছে:
class (Functor f) => MonoidalFunctor f where
mfEmpty :: f ()
mfAppend :: f a -> f b -> f ?
ফলাফলের ধরন কী mfAppend
? আমাদের দুটি স্বেচ্ছাচারী প্রকার রয়েছে যার সম্পর্কে আমরা কিছুই জানি না, তাই আমাদের কাছে অনেকগুলি বিকল্প নেই। সবচেয়ে বুদ্ধিমান জিনিস হ'ল উভয়কেই রাখা:
class (Functor f) => MonoidalFunctor f where
mfEmpty :: f ()
mfAppend :: f a -> f b -> f (a, b)
কোন পর্যায়ে mfAppend
এখন স্পষ্টতই zip
তালিকার সাধারণ সংস্করণ , এবং আমরা Applicative
সহজেই পুনর্গঠন করতে পারি:
mfPure x = fmap (\() -> x) mfEmpty
mfApply f x = fmap (\(f, x) -> f x) (mfAppend f x)
এটি আমাদের সনাক্ত করে যা pure
একটি এর সনাক্তকরণ উপাদানটির সাথে সম্পর্কিত Monoid
, সুতরাং এর জন্য অন্যান্য ভাল নামগুলি কোনও ইউনিট মান, নাল অপারেশন, বা এর মতো কিছু হতে পারে suggest
এটি দীর্ঘ ছিল, তাই সংক্ষেপে:
(<*>)
এটি কেবলমাত্র একটি পরিবর্তিত ফাংশন অ্যাপ্লিকেশন, সুতরাং আপনি এটিকে "এপি" বা "প্রয়োগ" হিসাবে পড়তে পারেন, বা এটি পুরোপুরিভাবে এলিডে ফাংশন অ্যাপ্লিকেশন হিসাবে ব্যবহার করতে পারেন।
(<*>)
এছাড়াও zipWith
তালিকাগুলিতে মোটামুটি সাধারণীকরণ করে, আপনি এটির সাথে "জিপ ফ্যান্টেক্টর" হিসাবে পড়তে পারেন, একইভাবে fmap
"সাথে একটি ফান্টারের সাথে মানচিত্র" পড়তে পারেন ।
প্রথমটি Applicative
টাইপ শ্রেণীর উদ্দেশ্যটির কাছাকাছি - নামটি যেমন সুপারিশ করে - তাই এটিই আমি প্রস্তাব করি।
আসলে, আমি সমস্ত উত্তোলিত অ্যাপ্লিকেশন অপারেটরগুলির উদার ব্যবহার এবং অ-উচ্চারণকে উত্সাহিত করি :
(<$>)
, যা একটিতে একক যুক্তি ফাংশনটি উত্তোলন করে Functor
(<*>)
, যা একটি এর মাধ্যমে একটি বহু-যুক্তি ফাংশনকে শৃঙ্খলাবদ্ধ করে Applicative
(=<<)
, যা একটি ফাংশনকে আবদ্ধ করে যা Monad
একটি বিদ্যমান গণনাতে প্রবেশ করে
তিনটিই হ'ল, কেবল নিয়মিত ফাংশন অ্যাপ্লিকেশন, কিছুটা মশলাদার।