সুতরাং এটি বোঝার সর্বোত্তম উপায় হ'ল এটি করা। নীচে পরিবর্তে foldlM
ব্যবহারের একটি বাস্তবায়ন আছে । এটি একটি ভাল অংশ, এটি চেষ্টা করুন এবং আমার প্রস্তাবিত সমাধানে পরে আসুন। উদাহরণটি এটিকে অর্জন করার জন্য আমি যে সমস্ত যুক্তি দিয়েছি তা ব্যাখ্যা করে, যা আপনার চেয়ে আলাদা হতে পারে এবং পক্ষপাত হতে পারে কারণ আমি ইতিমধ্যে কোনও ফাংশন সংগ্রহকারী ব্যবহার সম্পর্কে জানতাম।foldl
foldr
পদক্ষেপ 1 : এর foldlM
শর্তাবলী লিখতে চেষ্টা করুনfoldl
-- this doesn't compile because f returning type is (m b) and not just (b)
foldlM :: (Foldable t, Monad m) => (b -> a -> m b) -> b -> t a -> m b
foldlM f z0 xs = foldl f z0 xs
-- So let substitute f by some undefined f'
foldlM :: (Foldable t, Monad m) => (b -> a -> m b) -> b -> t a -> m b
foldlM f z0 xs = foldl f' z0 xs
where f' = undefined
-- cool, but f' should use f somehow in order to get the monadic behaviour
foldlM :: (Foldable t, Monad m) => (b -> a -> m b) -> b -> t a -> m b
foldlM f z0 xs = foldl f' z0 xs
where f' b a = f somethingIDontkNow
এখানে আপনি উপলব্ধি করেছেন যে f'
এটি খাঁটি এবং আপনার f
ম্যাচ টাইপ করার ফলাফলটি বের করতে হবে । কোনও একাধ্যগত মানকে 'এক্সট্রাক্ট' করার একমাত্র উপায় >>=
অপারেটরটির সাথে থাকে তবে এই জাতীয় অপারেটরটি ব্যবহার করার পরে এটি সঠিকভাবে মোড়ানো দরকার।
সুতরাং একটি উপসংহার হিসাবে: প্রতিবার আপনি শেষ করার সাথে সাথে আমি এই মোনাডকে পুরোপুরি খুলে ফেলতে চাই , কেবল হাল ছেড়ে দিন। সঠিক উপায় নয়
পদক্ষেপ 2 : আসুন প্রথমে ফোল্ডেবল হিসাবে ব্যবহার foldlM
করার শর্তে লিখতে চেষ্টা করি , কারণ এটি প্যাটার্ন ম্যাচ করা সহজ (যেমন আমাদের আসলে ব্যবহারের দরকার নেই )foldl
[]
fold
-- This is not very hard. It is pretty standard recursion schema. :)
foldlM' :: (Monad m) => (b -> a -> m b) -> b -> [a] -> m b
foldlM' f z0 [] = return z0
foldlM' f z0 (x:xs) = f z0 x >>= \c -> foldlM' f c xs
ঠিক আছে, এটা সহজ ছিল। foldl
তালিকাগুলির জন্য সাধারণ সংজ্ঞাটির সাথে সংজ্ঞাটি তুলনা করি
foldlM' :: (Monad m) => (b -> a -> m b) -> b -> [a] -> m b
foldlM' f z0 [] = return z0
foldlM' f z0 (x:xs) = f z0 x >>= \c -> foldlM' f c xs
myfoldl :: (b -> a -> b) -> b -> [a] -> b
myfoldl f z0 [] = z0
myfoldl f z0 (x:xs) = foldl f (f z0 x) xs
Cool !! তারা প্রায় অনেক একই। তুচ্ছ ঘটনাটি হুবহু একই জিনিস সম্পর্কে। Recursive ক্ষেত্রে সামান্য কিছুটা আলাদা হয়, তাহলে আপনি কিছু মত আরো লিখতে চাই: foldlM' f (f z0 x) xs
। কিন্তু 1 ম পদক্ষেপে হিসেবে কম্পাইল না হয়, তাই আপনার মনে হতে পারে ঠিক আছে, আমি চাই না প্রয়োগ করতে চান f
ঠিক যেমন একটি গণনার ধরে রাখুন এবং সঙ্গে এটি রচনা করতে, >>=
। আমি আরও কিছু লিখতে চাই foldlM' f (f z0 x >>=) xs
যদি এটি বুদ্ধিমান ছিল ...
পদক্ষেপ 3 বুঝতে পারেন যে আপনি যা জমা করতে চান তা কোনও ফাংশন রচনা এবং ফলাফল নয়। ( এখানে আমি সম্ভবত এটি পক্ষপাতিত্ব করছি যে আপনি এটি পোস্ট করেছেন বলে আমি এটি ইতিমধ্যে জানতাম )।
foldlM :: (Foldable t, Monad m) => (b -> a -> m b) -> b -> t a -> m b
foldlM f z0 xs = foldl f' initFunc xs
where initFunc = undefined :: b -> m b
f' = undefined :: (b -> m b) -> a -> (b -> m b) -- This type signature can be deduce because f' should be applied to initFunc and a's from t a.
initFunc
ধাপ 2 (পুনরাবৃত্ত সংজ্ঞা) থেকে আমাদের জ্ঞানটি প্রকার এবং ব্যবহার করে আমরা তা অনুমান করতে পারি initFunc = return
। সংজ্ঞাটি ব্যবহার করা উচিত এবং f'
তা জেনেও সম্পূর্ণ করা যায় ।f'
f
>>=
foldlM :: (Foldable t, Monad m) => (b -> a -> m b) -> b -> t a -> m b
foldlM f z0 xs = foldl f' return xs z0
-- ^^^^^^
-- |- Initial value
where f' b a = \bvalue -> b bvalue >>= \bresult -> f bresult a -- this is equivalent to (b >=> \result -> f result a) which captures the sequence behaviour of the implementation
-- ^ ^^^^^^ ^^^^^^^
-- | | |- This is the result of previous computation
-- | |- f' should return a function b -> m b. Any time you have to return a function, start writing a lambda
-- |- This b is the accumulated value and has type b -> m b
-- Following the types you can write this with enough practise
আপনি দেখতে পাচ্ছেন, এটি করা খুব কঠিন নয়। এটির অনুশীলন দরকার, তবে আমি পেশাদার হেসেল বিকাশকারী নই এবং আমি নিজেই এটি করতে পারতাম, এটি অনুশীলনের বিষয়