প্যাকেজটি Control.Monad.Writer
ডেটা কনস্ট্রাক্টর রফতানি করে না Writer
। আমার ধারণা, লায়াহ লেখা হয়েছিল যখন এটি আলাদা ছিল।
GCI এ MonadWriter টাইপক্লাস ব্যবহার করে
পরিবর্তে, আপনি writer
ফাংশনটি ব্যবহার করে লেখক তৈরি করেন । উদাহরণস্বরূপ, একটি ঘিসি অধিবেশনে আমি করতে পারি
ghci> import Control.Monad.Writer
ghci> let logNumber x = writer (x, ["Got number: " ++ show x])
এখন logNumber
একটি ফাংশন যা লেখক তৈরি করে। আমি এর ধরণের জন্য জিজ্ঞাসা করতে পারি:
ghci> :t logNumber
logNumber :: (Show a, MonadWriter [String] m) => a -> m a
যা আমাকে জানিয়েছে যে অনুমিত টাইপ কোনও ফাংশন নয় যা কোনও নির্দিষ্ট লেখককে ফিরিয়ে দেয় , বরং এমন কোনও কিছু যা MonadWriter
প্রকারের শ্রেণিকে প্রয়োগ করে । আমি এখন এটি ব্যবহার করতে পারি:
ghci> let multWithLog = do { a <- logNumber 3; b <- logNumber 5; return (a*b) }
:: Writer [String] Int
(ইনপুট আসলে এক লাইনে সমস্ত প্রবেশ করিয়েছে)। এখানে আমি প্রকার নির্দিষ্ট করে থাকেন multWithLog
হতে Writer [String] Int
। এখন আমি এটি চালাতে পারি:
ghci> runWriter multWithLog
(15, ["Got number: 3","Got number: 5"])
এবং আপনি দেখতে পান যে আমরা মধ্যবর্তী অপারেশনগুলির সমস্ত লগ করছি।
কোডটি এভাবে লেখা হয় কেন?
মোটেই MonadWriter
টাইপ ক্লাস তৈরি করতে বিরক্ত করবেন কেন ? কারণটি হ'ল মোনাড ট্রান্সফর্মারগুলি দিয়ে। আপনি যেমনটি সঠিকভাবে উপলব্ধি করেছেন, বাস্তবায়নের সহজতম উপায় Writer
হ'ল একটি জোড়ার শীর্ষে একটি নতুন প্রকারের মোড়ক:
newtype Writer w a = Writer { runWriter :: (a,w) }
আপনি এটির জন্য একটি মোনাড উদাহরণ ঘোষণা করতে পারেন এবং তারপরে ফাংশনটি লিখতে পারেন
tell :: Monoid w => w -> Writer w ()
যা কেবল তার ইনপুট লগ করে। এখন ধরা যাক আপনি এমন একটি মোনাড চান যাতে লগিংয়ের ক্ষমতা রয়েছে তবে অন্য কিছু করে - বলুন এটি পরিবেশ থেকেও পড়তে পারে। আপনি এটি হিসাবে বাস্তবায়ন চাই
type RW r w a = ReaderT r (Writer w a)
এখন লেখক ReaderT
মোনাড ট্রান্সফর্মারের ভিতরে রয়েছে , আপনি যদি আউটপুট লগ করতে চান তবে আপনি ব্যবহার করতে পারবেন না tell w
(কারণ এটি কেবল মোড়কানো লেখকদের সাথে কাজ করে) তবে আপনাকে ব্যবহার করতে হবে lift $ tell w
, যা tell
ফাংশনটিকে "উত্তোলন" করে ReaderT
যাতে এটি অ্যাক্সেস করতে পারে অন্তর্ লেখক মনাদ। আপনি যদি দুটি স্তর ট্রান্সফর্মার চেয়েছিলেন (বলুন যে আপনি ত্রুটি পরিচালনা করার পাশাপাশি যুক্ত করতে চান) তবে আপনাকে ব্যবহারের প্রয়োজন হবেlift $ lift $ tell w
। এটি দ্রুত অস্বাস্থ্যকর হয়ে পড়ে।
পরিবর্তে, একটি প্রকার শ্রেণি নির্ধারণ করে আমরা কোনও লেখকের চারপাশে যে কোনও মোনাড ট্রান্সফর্মার মোড়ককে লেখকের নিজের উদাহরণ হিসাবে তৈরি করতে পারি। উদাহরণ স্বরূপ,
instance (Monoid w, MonadWriter w m) => MonadWriter w (ReaderT r m)
এটি হ'ল যদি w
একঘেয়ে হয় এবং m
এটি একটি হয় MonadWriter w
তবে ReaderT r m
এটিও একটি MonadWriter w
। এর অর্থ হ'ল আমরা tell
ফাংশনটি সরাসরি মোনাড ট্রান্সফর্মারের মাধ্যমে এটিকে উত্থাপিত করে বিরক্ত না করেই পরিবর্তিত মনডের উপরে সরাসরি ব্যবহার করতে পারি ।