এই জাতীয় ভাঁজ সংজ্ঞা লিখতে কারও জন্য কোন ধরণের জ্ঞান বা প্রশিক্ষণের প্রয়োজন? [বন্ধ]


9

সম্প্রতি, আমি আমার কিছু বাস্তব কেস প্রোডাকশন সিস্টেমে হাস্কেলকে ব্যবহার করার চেষ্টা করছি। হাস্কেল টাইপ সিস্টেমটি সত্যিই আমাকে দুর্দান্ত সহায়তা দেয়। উদাহরণস্বরূপ, যখন আমি বুঝতে পারি যে আমার টাইপের কিছু ফাংশন প্রয়োজন

f :: (Foldable t, Monad m) => ( a-> b -> m b) -> b -> t a -> m b

আসলে মত ফাংশন আছে foldM, foldlMএবং foldrM

যাইহোক, আমাকে যা সত্যই হতবাক করেছিল তা হ'ল এই ক্রিয়াগুলির সংজ্ঞা, যেমন:

foldlM :: (Foldable t, Monad m) => (b -> a -> m b) -> b -> t a -> m b
foldlM f z0 xs = foldr f' return xs z0
  where f' x k z = f z x >>= k

সুতরাং ফাংশন f'অবশ্যই প্রকারের হতে হবে:

f' :: a -> b -> b

যেমনটি প্রয়োজনীয় foldr, তারপরে bঅবশ্যই বিনয়ী হওয়া উচিত *-> m *, যাতে সম্পূর্ণ সংজ্ঞাটি foldlMবোঝায়।

আরেকটি উদাহরণের মধ্যে liftA2এবং এর সংজ্ঞা রয়েছে<*>

(<*>) :: f (a -> b) -> f a -> f b
(<*>) = liftA2 id

liftA2 :: (a -> b -> c) -> f a -> f b -> f c
liftA2 f x = (<*>) (fmap f x)

উত্স কোডে উঁকি দেওয়ার আগে আমি আমার নিজস্ব কিছু সমাধান চেষ্টা করেছি। তবে ব্যবধানটি এত বিশাল যে আমি ভবিষ্যতে কোডের কতগুলি লাইন লিখব তা বিবেচনা করেই আমি এই সমাধানটি নিয়ে আসতে পারি না বলে আমি মনে করি না।

সুতরাং আমার প্রশ্নটি হল যে কারও পক্ষে এমন উচ্চ বিমূর্ত স্তরে যুক্তি দেখানোর জন্য কোন ধরণের জ্ঞান বা কোন নির্দিষ্ট গণিতের শাখা প্রয়োজনীয়।

আমি জানি বিভাগের তত্ত্বটি কিছু সহায়তা দিতে পারে এবং আমি দীর্ঘ সময় ধরে এই দুর্দান্ত বক্তৃতাটি অনুসরণ করছি এবং এখনও এটিতে কাজ করছি।


13
হাস্কেল একটি ভাষা। এর অনেক শব্দ রয়েছে এবং সেই শব্দগুলির বেশিরভাগই বিভিন্ন উপায়ে ব্যবহার করা যেতে পারে। আপনি যখন একটি নতুন ভাষা শিখছেন, বছরের পর বছর ধরে অনেক বাক্য এবং বুদ্ধিমানের অর্থ হয় না। তবে আপনি যত বেশি এটি ব্যবহার করেন, তত বেশি আপনি পরিচিত নিদর্শন দেখতে পাবেন এবং যে জিনিসগুলি আপনি একবার ভীতি প্রদর্শন এবং উন্নত বলে মনে করেছিলেন তা স্বাভাবিকভাবেই আসে। আরাম করুন।
luqui

উত্তর:


3

সাধারণভাবে, যুক্তি ইত্যাদি, আমি কল্পনা করব would তবে আপনি এটি করে এটি শিখতে পারেন। :) সময়ের সাথে আপনি কিছু নিদর্শন লক্ষ্য করুন, কিছু কৌশল অবলম্বন করুন।

foldrঅতিরিক্ত যুক্তিযুক্ত জিনিস সহ এটি পছন্দ করুন । কেউ কেউ এটিকে ফাংশনগুলিতে ভাঁজ হিসাবে দেখেন যাতে তাদের মাধ্যমে একত্রিত হতে পারে .এবং id(যা কখনও কখনও সত্যই হয় <=<এবং return),

foldr g z xs  =  foldr ($) z . map g $ xs
              =  foldr (.) id (map g xs) z
         ~/=  foldr (<=<) return (map g xs) z
{-
  (\f -> f . f) :: (a -> a) -> (a -> a)

  (\f -> f <=< f) :: Monad m => (a -> m a) -> (a -> m a)
                            (still just a type, not a kind)
-}

কেউ কেউ এটিকে সহজ, সিনট্যাক্টিকাল পদগুলিতে বোঝা আরও সহজ বলে মনে করেন

foldr g z [a,b,c,...,n] s =
     g a (foldr g z [b,c,...,n]) s

সুতরাং যখন gএর দ্বিতীয় যুক্তিতে অ-কঠোর হয় s, তখন একটি উদাহরণ হিসাবে ডানদিকে ভাঁজ করা সত্ত্বেও, বাম দিক থেকে বরাবর প্রস্থান করা রাষ্ট্র হিসাবে পরিবেশন করতে পারে।


1
আপনাকে অনেক ধন্যবাদ, আমি এই সংজ্ঞাটি অনন্য কিনা এবং এখানে ক্লাইসলি রচনার ব্যবহার আশা করিনি কিনা তা জানার চেষ্টা করছিলাম। এই উত্তর সত্যিই আমার সন্দেহ সমাধান।
থিওডোরা

আপনাকে স্বাগতম. :)
নেস

4

সুতরাং এটি বোঝার সর্বোত্তম উপায় হ'ল এটি করা। নীচে পরিবর্তে foldlMব্যবহারের একটি বাস্তবায়ন আছে । এটি একটি ভাল অংশ, এটি চেষ্টা করুন এবং আমার প্রস্তাবিত সমাধানে পরে আসুন। উদাহরণটি এটিকে অর্জন করার জন্য আমি যে সমস্ত যুক্তি দিয়েছি তা ব্যাখ্যা করে, যা আপনার চেয়ে আলাদা হতে পারে এবং পক্ষপাত হতে পারে কারণ আমি ইতিমধ্যে কোনও ফাংশন সংগ্রহকারী ব্যবহার সম্পর্কে জানতাম।foldlfoldr

পদক্ষেপ 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

আপনি দেখতে পাচ্ছেন, এটি করা খুব কঠিন নয়। এটির অনুশীলন দরকার, তবে আমি পেশাদার হেসেল বিকাশকারী নই এবং আমি নিজেই এটি করতে পারতাম, এটি অনুশীলনের বিষয়


1
আমি এখানে ডান ভাঁজ থেকে বাম ভাঁজ বুঝতে সহজতর কি তা সত্যই দেখতে পাচ্ছি না। ডান ভাঁজ অসীম কাঠামোগুলির জন্য কার্যকর ফলাফল তৈরি করার এবং সাধারণ Monadউদাহরণগুলির জন্য দক্ষ হওয়ার সম্ভাবনা অনেক বেশি ।
dfeuer

@ ডিফিউয়ার এর মূল বিষয়টি একটি সহজ উদাহরণ না দেখানো নয়, তবে ওপি'র জন্য উপযুক্ত অনুশীলনের প্রস্তাব দেওয়া এবং সমাধানের যৌক্তিক যুক্তি প্রকাশ করা, এটি প্রমাণ করার চেষ্টা করা যে সুপার মাস্টার হেস্কেলার হওয়ার প্রয়োজন নেই যেমন একটি সমাধান। দক্ষতা সম্পর্কে
দিকনির্দেশগুলি আমলে

3

এর মতো একটি ফাংশন লিখতে আপনার গণিতে কোনও নির্দিষ্ট জ্ঞানের প্রয়োজন নেই foldM। আমি ইতিমধ্যে 4 বছর ধরে উত্পাদনে হাস্কেল ব্যবহার করছি, এবং আমি এই সংজ্ঞাটি বোঝার জন্যও লড়াই করছি foldM। তবে এটি বেশিরভাগ ক্ষেত্রেই এটি খারাপ লেখা। আপনি কিছু অস্পষ্ট কোড বুঝতে না পারলে দয়া করে এটি ব্যক্তিগত ত্রুটি হিসাবে গ্রহণ করবেন না। এখানে এর আরও পাঠযোগ্য সংস্করণfoldlM

foldlM
    :: forall t m a b .
       (Foldable t, Monad m)
    => (b -> a -> m b)  -- ^ Monadic action
    -> b                -- ^ Starting accumulator
    -> t a              -- ^ List of values
    -> m b              -- ^ Computation result inside a monad
foldlM f z xs = (foldr step pure xs) z
  where
    step :: a -> (b -> m b) -> b -> m b
    step cur next acc = do
        result <- f acc cur
        next result

এই ফাংশনটি এখনও সবচেয়ে সহজ নয়। বেশিরভাগ ক্ষেত্রে এটির foldrমধ্যবর্তী সঞ্চালক একটি ফাংশন যেখানে অ-সাধারণ ব্যবহার রয়েছে । তবে আপনি কয়েকটি মাই দেখতে পাবেন যা এই জাতীয় সংজ্ঞাটিকে আরও পাঠযোগ্য করে তোলে:

  1. ফাংশন যুক্তি সম্পর্কে মন্তব্য।
  2. আরও ভাল আর্গুমেন্টের নাম (এখনও সংক্ষিপ্ত এবং মূর্তিযুক্ত, তবে তারা কমপক্ষে আরও পঠনযোগ্য)।
  3. ভিতরে ফাংশনটির সুস্পষ্ট প্রকারের স্বাক্ষর where(যাতে আপনি যুক্তিগুলির আকারটি জানেন)।

এই জাতীয় ফাংশন দেখার পরে, আপনি এখন সংজ্ঞাটি ধাপে-ধাপে প্রসারিত করতে ইক্যুয়াল যুক্তি কৌশলটি সম্পাদন করতে পারেন এবং দেখুন এটি কীভাবে কাজ করে। এই জাতীয় ফাংশন নিয়ে আসার ক্ষমতা অভিজ্ঞতা নিয়ে আসে। আমার কাছে গণিতের শক্তিশালী দক্ষতা নেই, এবং এই ফাংশনটি কোনও সাধারণ হাস্কেল ফাংশন নয়। তবে আপনার যত বেশি অনুশীলন হবে তা ততই ভাল হবে :)

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.