উত্তর:
গাণিতিক ধারণার চেয়ে তুলনামূলক নকশার নকশা বেশি (যদিও আমি আশা করি কাছাকাছি কেউ এখন লিফটগুলি কীভাবে কোনও বিভাগ বা কিছু দেখিয়ে আমার খণ্ডন করবে)।
সাধারণত আপনার কাছে প্যারামিটারের সাথে কিছু ডেটা টাইপ থাকে। কিছুটা এইরকম
data Foo a = Foo { ...stuff here ...}
আপনাকে খুঁজে যে ব্যবহার অনেকটা ধরুন Foo
(সাংখ্যিক ধরনের নেওয়া Int
, Double
ইত্যাদি) এবং আপনি লিখতে কোডটি এই সংখ্যা unwraps, যোগ করে বা তাদের তা বৃদ্ধি পায়, এবং তারপর গোপন এগুলি ব্যাক আপ করা রাখা। আপনি আন-র্যাপ-ও-মোড়কের কোডটি একবার লিখে শর্ট সার্কিট করতে পারেন। এই ফাংশনটিকে traditionতিহ্যগতভাবে "লিফট" বলা হয় কারণ এটি দেখতে এরকম দেখাচ্ছে:
liftFoo2 :: (a -> b -> c) -> Foo a -> Foo b -> Foo c
অন্য কথায় আপনার একটি ফাংশন রয়েছে যা একটি দ্বি-আর্গুমেন্ট ফাংশন নেয় (যেমন (+)
অপারেটর) এবং এটিকে ফুসের সমতুল্য ফাংশনে পরিণত করে।
সুতরাং এখন আপনি লিখতে পারেন
addFoo = liftFoo2 (+)
সম্পাদনা করুন: আরও তথ্য
আপনার অবশ্যই থাকতে পারে liftFoo3
, liftFoo4
ইত্যাদি। তবে এটি প্রায়শই প্রয়োজন হয় না।
পর্যবেক্ষণ দিয়ে শুরু করুন
liftFoo1 :: (a -> b) -> Foo a -> Foo b
তবে তা ঠিক তেমনই fmap
। বরং liftFoo1
আপনি লিখতে চেয়েছিলেন
instance Functor Foo where
fmap f foo = ...
আপনি যদি সত্যিই সম্পূর্ণ নিয়মিততা চান তবে আপনি বলতে পারেন
liftFoo1 = fmap
আপনি যদি Foo
কোনও ফান্টর তৈরি করতে পারেন তবে সম্ভবত আপনি এটি একটি প্রয়োগমূলক ফান্টর তৈরি করতে পারেন। আসলে, আপনি যদি লিখতে পারেন liftFoo2
তবে আবেদনকারী উদাহরণটি দেখতে এরকম দেখাচ্ছে:
import Control.Applicative
instance Applicative Foo where
pure x = Foo $ ... -- Wrap 'x' inside a Foo.
(<*>) = liftFoo2 ($)
(<*>)
Foo এর জন্য অপারেটর টাইপ হয়েছে
(<*>) :: Foo (a -> b) -> Foo a -> Foo b
এটি মোড়ানো মানটির সাথে মোড়ক ফাংশনটি প্রয়োগ করে। সুতরাং আপনি যদি বাস্তবায়ন করতে পারেন liftFoo2
তবে আপনি এটি এর নিরিখে এটি লিখতে পারেন। বা আপনি এটি সরাসরি বাস্তবায়ন করতে পারেন এবং এতে বিরক্ত করবেন না liftFoo2
, কারণ Control.Applicative
মডিউলটি অন্তর্ভুক্ত রয়েছে
liftA2 :: Applicative f => (a -> b -> c) -> f a -> f b -> f c
এবং একইভাবে liftA
এবং আছে liftA3
। কিন্তু আপনি আসলে এগুলি খুব বেশি ব্যবহার করেন না কারণ অন্য অপারেটর রয়েছে
(<$>) = fmap
এটি আপনাকে লিখতে দেয়:
result = myFunction <$> arg1 <*> arg2 <*> arg3 <*> arg4
শব্দটি myFunction <$> arg1
ফু-র মধ্যে আবৃত একটি নতুন ফাংশন দেয়। এটি পরিবর্তে পরবর্তী যুক্তিতে প্রয়োগ করা যেতে পারে (<*>)
ইত্যাদি on সুতরাং এখন প্রতিটি আরটিটির জন্য একটি লিফট ফাংশন না করে আপনার কাছে কেবল আবেদনকারীদের একটি ডেইজি চেইন রয়েছে।
lift id == id
এবং lift (f . g) == (lift f) . (lift g)
।
id
এবং .
পরিচয় তীর তীর কিছু বিষয়শ্রেণীতে রচনা যথাক্রমে হয়। সাধারণত হাস্কেলের কথা বলার সময়, প্রশ্নে বিভাগটি "হাস্ক", যার তীরগুলি হ্যাস্কেল ফাংশন (অন্য কথায়, id
এবং .
আপনি জানেন এবং পছন্দ করেন এমন হাস্কেল ফাংশনগুলি উল্লেখ করুন)।
instance Functor Foo
, না instance Foo Functor
? আমি নিজেকে সম্পাদনা করব তবে আমি 100% নিশ্চিত নই।
পল এবং ইয়ারছু উভয়ই ভাল ব্যাখ্যা।
আমি যুক্ত করতে চাই যে ফাংশনটি তুলে নেওয়া হচ্ছে তাতে একটি স্বেচ্ছাসেবী যুক্তি থাকতে পারে এবং তাদের একই ধরণের হতে হবে না। উদাহরণস্বরূপ, আপনি একটি লিফটফু 1 সংজ্ঞায়িত করতে পারেন:
liftFoo1 :: (a -> b) -> Foo a -> Foo b
সাধারণভাবে, 1 টি যুক্তিযুক্ত ফাংশনগুলির উত্তোলন টাইপ শ্রেণিতে ধরা পড়ে Functor
এবং উত্তোলন অপারেশন বলা হয় fmap
:
fmap :: Functor f => (a -> b) -> f a -> f b
liftFoo1
এর ধরণের সাথে মিলটি নোট করুন । আসলে আপনার যদি থাকে তবে আপনি একটি উদাহরণ liftFoo1
তৈরি করতে পারেন :Foo
Functor
instance Functor Foo where
fmap = liftFoo1
তদ্ব্যতীত, আর্গুমেন্ট একটি অবাধ নম্বরে তুলে সামান্যীকরণ বলা হয় আবেদন শৈলী । যতক্ষণ না আপনি নির্দিষ্ট সংখ্যক যুক্তি দিয়ে ফাংশনগুলির উত্তোলন উপলব্ধি না করেন ততক্ষণ এটিকে ডাইভিং করবেন না। তবে আপনি যখন করবেন, শিখুন একটি হাস্কেলের এ সম্পর্কে একটি ভাল অধ্যায় রয়েছে। Typeclassopedia বর্ণনা আরেকটি ভাল নথি Functor এবং আবেদন (পাশাপাশি অন্যান্য টাইপ শ্রেণীর; দস্তাবেজটি সঠিক অধ্যায় স্ক্রোল ডাউন)।
আশাকরি এটা সাহায্য করবে!
আসুন একটি উদাহরণ দিয়ে শুরু করা যাক (পরিষ্কার উপস্থাপনার জন্য কিছু সাদা স্থান যুক্ত করা হয়েছে):
> import Control.Applicative
> replicate 3 'a'
"aaa"
> :t replicate
replicate :: Int -> b -> [b]
> :t liftA2
liftA2 :: (Applicative f) => (a -> b -> c) -> (f a -> f b -> f c)
> :t liftA2 replicate
liftA2 replicate :: (Applicative f) => f Int -> f b -> f [b]
> (liftA2 replicate) [1,2,3] ['a','b','c']
["a","b","c","aa","bb","cc","aaa","bbb","ccc"]
> ['a','b','c']
"abc"
liftA2
একটি ফাংশন প্লেইন ধরনের একটি ফাংশন রূপান্তরিত একই একটি আবৃত ধরনেরApplicative
তালিকা, হিসাবে, IO
ইত্যাদি
আর একটি সাধারণ লিফট lift
এসেছে Control.Monad.Trans
। এটি একটি মোনাডের এক একাত্মক ক্রিয়াকে রূপান্তরিত মনাদের ক্রিয়ায় রূপান্তর করে।
সাধারণভাবে, "লিফট" কোনও ফাংশন / ক্রিয়াকে "মোড়ানো" প্রকারে উত্তোলন করে (যাতে মূল ফাংশনটি "মোড়কের নীচে" কাজ করে)।
এটি বোঝার সর্বোত্তম উপায় এবং মনডস ইত্যাদি, এবং কেন তারা কার্যকর তা বোঝার জন্য সম্ভবত এটি কোড করা এবং ব্যবহার করা। আপনি যদি আগে কোড করেছেন এমন কিছু যদি থাকে তবে আপনি সন্দেহ করেন যে এগুলি থেকে লাভবান হতে পারে (উদাহরণস্বরূপ এটি কোডটি সংক্ষিপ্ত করে তুলবে ইত্যাদি), কেবল এটি চেষ্টা করে দেখুন এবং আপনি সহজেই ধারণাটি উপলব্ধি করতে পারবেন।
উত্তোলন একটি ধারণা যা আপনাকে কোনও ফাংশনটিকে অন্য (সাধারণত আরও সাধারণ) সেটিংয়ের মধ্যে সম্পর্কিত ফাংশনে রূপান্তর করতে দেয়
http://haskell.org/haskellwiki/ লিফটিং এ একবার দেখুন
এই চকচকে টিউটোরিয়াল অনুসারে , একটি ফান্টেক্টর হ'ল কিছু ধারক (যেমন Maybe<a>
, List<a>
বা Tree<a>
এটি অন্য কোনও ধরণের উপাদান সংরক্ষণ করতে পারে a
)। আমি <a>
উপাদান ধরণের জন্য জাভা জেনেরিক সংকেত ব্যবহার করেছি a
এবং উপাদানগুলিকে গাছের বেরি হিসাবে ভাবি Tree<a>
। একটি ফাংশন রয়েছে fmap
, যা একটি উপাদান রূপান্তর ফাংশন a->b
এবং ধারক গ্রহণ করে functor<a>
। এটি a->b
কার্যকরভাবে এটিকে রূপান্তরিত করে ধারকটির প্রতিটি উপাদানকে প্রয়োগ করে functor<b>
। যখন শুধুমাত্র প্রথম যুক্তি সরবরাহ করা হয়, a->b
, fmap
জন্য অপেক্ষা functor<a>
। অর্থাত, a->b
একা সরবরাহ করা এই উপাদান-স্তরের ফাংশনটিকে functor<a> -> functor<b>
পাত্রে সঞ্চালিত ফাংশনে রূপান্তরিত করে । এটিকে বলা হয় উত্তোলনফাংশন। কারণ ধারক এছাড়াও বলা হয় একটি functor , Functors বদলে Monads উত্তোলন জন্য একটি পূর্বশর্ত আছে। মনডা উত্তোলনের জন্য "সমান্তরাল" ধরণের। উভয়ই ফান্টেক্টর ধারণার উপর নির্ভর করে এবং করে f<a> -> f<b>
। পার্থক্যটি হ'ল a->b
লিফটিংটি রূপান্তরটির জন্য ব্যবহার করে যেখানে মোনাদকে ব্যবহারকারীর সংজ্ঞা দিতে হয় a -> f<b>
।
r
কারওর কাছ থেকে এক ধরণের ফাংশন (আসুন c
বিভিন্নতার জন্য ব্যবহার করুন ), হ'ল ফান্টেক্টর। তারা কোনও "থাকে না" c
। এই উদাহরণে, fmap হ'ল ফাংশন রচনা, একটি a -> b
ফাংশন এবং একটি গ্রহণ করে r -> a
, আপনাকে একটি নতুন, r -> b
ফাংশন দেয়। তবুও কোনও ধারক নেই A তবুও যদি আমি পারতাম তবে আমি চূড়ান্ত বাক্যটির জন্য এটি আবার চিহ্নিত করতাম।
fmap
একটি ফাংশন, এবং কোনও কিছুর জন্য "অপেক্ষা" করে না; "পাত্র" একটি ফান্টেক্টর হ'ল উত্তোলনের পুরো পয়েন্ট । এছাড়াও, মনাদাস হ'ল, যদি কিছু থাকে তবে উত্তোলনের দ্বৈত ধারণা: একটি মোনাড আপনাকে এমন কিছু ব্যবহার করতে দেয় যা বেশ কয়েকটি ইতিবাচক সংখ্যক বার উঠিয়ে নেওয়া হয়েছে, যেন এটি কেবল একবার উত্তোলন করা হয়েছিল - এটি আরও চাটুকার হিসাবে পরিচিত ।
To wait
, to expect
, to anticipate
প্রতিশব্দের হয়। "ফাংশন অপেক্ষা করে" বলে আমার অর্থ "ফাংশন প্রত্যাশা"।
b = 5 : a
এবং f 0 = 55
f n = g n
উভয়ই "ধারক" কে সিউডো- মিউটেশন করার সাথে জড়িত। এছাড়াও তালিকাগুলি সাধারণত মেমরিতে সম্পূর্ণরূপে সঞ্চিত থাকে যখন কার্যকরীভাবে একটি গণনা হিসাবে সাধারণত সংরক্ষণ করা হয়। কিন্তু মেমোজাইজিং / মনরফিক তালিকাগুলি যেগুলি উভয়ের কলগুলির মধ্যে সংরক্ষণ করা হয় না সেই ধারণাটি ছড়িয়ে দেয়।