কারি বা আংশিক প্রয়োগ সম্পর্কে বিশেষ কী?


9

আমি প্রতিদিন ফাংশনাল প্রোগ্রামিংয়ের নিবন্ধগুলি পড়ছি এবং যথাসম্ভব কিছু অনুশীলন প্রয়োগ করার চেষ্টা করছি। তবে আমি বুঝতে পারি না কারী বা আংশিক প্রয়োগে অনন্য কী।

এই গ্রোভি কোডটি উদাহরণ হিসাবে নিন:

def mul = { a, b -> a * b }
def tripler1 = mul.curry(3)
def tripler2 = { mul(3, it) }

আমি বুঝতে পারছি না tripler1এবং এর মধ্যে পার্থক্য কী tripler2। তারা দুজন কি এক নয়? 'কারিটিং' খাঁটি বা আংশিক কার্যকরী ভাষায় যেমন গ্রোভি, স্কেলা, হাস্কেল ইত্যাদিতে সমর্থিত তবে আমি একই জিনিস (বাম-তরকারী, ডান-তরকারী, এন-কারি বা আংশিক প্রয়োগ) কেবল অন্য নাম বা বেনাম তৈরি করে করতে পারি ফাংশন বা সমাপ্তি যা tripler2বেশিরভাগ ভাষায় (এমনকি সি।) মূল ফাংশনে (যেমন ) পরামিতিগুলি ফরোয়ার্ড করে দেবে

আমি কি এখানে কিছু মিস করছি? আমি আমার গ্রিল অ্যাপ্লিকেশনগুলিতে কারিঙ এবং আংশিক অ্যাপ্লিকেশন ব্যবহার করতে পারি এমন জায়গাগুলি রয়েছে তবে আমি তা করতে দ্বিধা বোধ করছি কারণ আমি নিজেকে জিজ্ঞাসা করছি "এটি কীভাবে আলাদা?"

আমাকে আলোকিত করুন।

সম্পাদনা: আপনি কি বলছেন যে আংশিক অ্যাপ্লিকেশন / কারি করানো অন্য ফাংশনটি তৈরি / কল করার চেয়ে কেবল আরও কার্যকর যা ডিফল্ট পরামিতিগুলিকে মূল ফাংশনে ফরোয়ার্ড করে?


1
কেউ দয়া করে "তরকারী" বা "তরকারী" ট্যাগ তৈরি করতে পারেন?
Vigneshwaran

আপনি কিভাবে সি তে কারি?
জর্জিও

এটি সম্ভবত সত্যিই আরো আংশিক আবেদনের কথা programmers.stackexchange.com/questions/152868/...
জে।

1
@ বিগনেশ্বরান: এএফআইএইসি আপনার কারিগরি সমর্থন করে এমন ভাষায় অন্য একটি ক্রিয়াকলাপ তৈরি করার দরকার নেই। উদাহরণস্বরূপ, হাস্কেলের f x y = x + yমানে এটি fএমন একটি ফাংশন যা একটি ইনট প্যারামিটার নেয়। f x( fপ্রয়োগ করা হয় x) এর ফলাফলটি এমন একটি ফাংশন যা একটি ইনট প্যারামিটার নেয়। ফলাফল f x y(বা (f x) y, অর্থাৎ f xপ্রয়োগ করা y) এমন একটি অভিব্যক্তি যা কোনও ইনপুট পরামিতি নেয় না এবং হ্রাস করে মূল্যায়ন করা হয় x + y
জর্জিও

1
আপনি একই জিনিস অর্জন করতে পারেন, তবে সি দিয়ে আপনি যে পরিমাণ পরিশ্রম করেছেন তা অনেক বেশি বেদনাদায়ক এবং হ্যাশকের মতো ভাষার মতো দক্ষ নয় যেখানে এটি পূর্বনির্ধারিত আচরণ
ড্যানিয়েল গ্রেটজার

উত্তর:


8

কার্য়িং হচ্ছে এমন কোনও ফাংশনটি ঘুরিয়ে / প্রতিনিধিত্ব করা সম্পর্কে যা এন ফাংশনগুলিতে এন ইনপুট গ্রহণ করে যা প্রতিটি 1 ইনপুট নেয়। আংশিক অ্যাপ্লিকেশনটি কোনও ফাংশনে কিছু ইনপুট স্থির করতে চলেছে।

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

কারিঙ নিজেই দরকারী কারণ এটি আপনাকে যে কোনও জায়গায় নিখরচায় চাইলে আংশিক অ্যাপ্লিকেশন দেয় কারণ আপনার আর আংশিক প্রয়োগের মতো কোনও ফাংশন প্রয়োজন নেই bind1st


হয় curryingকিছু নির্দিষ্ট খাঁজকাটা অথবা ভাষাতে প্রযোজ্য?
উভচর

@ ফোমাপাইল এটির এমন কিছু যা ভাষাগুলিতে প্রযোজ্য তবে বিদ্রূপাত্মক গ্রোভি তরকারি সত্যিই এটি প্রোগ্রামার
জে কে।

@jk। আপনি কি বলছেন যে কারিগরীকরণ / আংশিক অ্যাপ্লিকেশন অন্য ফাংশন তৈরি এবং কল করার চেয়ে বেশি দক্ষ?
ভিগনেশ্বরান

2
@ বিগনেশ্বরান - এটি অগত্যা আরও পারফরম্যান্ট নয়, তবে প্রোগ্রামারের সময়ের ক্ষেত্রে এটি অবশ্যই আরও দক্ষ। এছাড়াও নোট করুন যে কারিঙ করার সময় অনেকগুলি কার্যকরী ভাষা দ্বারা সমর্থন করা হয় তবে সাধারণত ওও বা পদ্ধতিগত ভাষায় সমর্থিত হয় না। (বা কমপক্ষে, ভাষা নিজেই নয়))
স্টিফেন সি

6

তবে আমি একই জিনিসটি করতে পারি (বাম-তরকারী, ডান-কারি, এন-কারি বা আংশিক অ্যাপ্লিকেশন) কেবলমাত্র একটি নামযুক্ত বা বেনাম ফাংশন বা বন্ধ করে যা বেশিরভাগ ভাষায় মূল ফাংশনে (ট্রিপল 2 এর মতো) পরামিতিগুলি ফরোয়ার্ড করবে ( এমনকি সি।)

এবং অপ্টিমাইজার এটি দেখবে এবং তত্ক্ষণাত এটি বুঝতে পারে এমন কিছুতে চলে যাবে to শেষ ব্যবহারকারীর জন্য কারিঙ করা একটি দুর্দান্ত ছোট কৌশল, তবে একটি ভাষা নকশার দিক থেকে আরও ভাল বেনিফিট রয়েছে। এটা সত্যিই সব পদ্ধতি ইউনারী যেমন হ্যান্ডেল সুন্দর A -> Bযেখানে Bঅন্য পদ্ধতি হতে পারে।

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


6

যেমন @ জে কে। ইঙ্গিত দেওয়া হয়, তরঙ্গীকরণ কোড আরও সাধারণ করতে সহায়তা করতে পারে।

উদাহরণস্বরূপ, ধরুন আপনার এই তিনটি ফাংশন ছিল (হাসকেলে):

> let q a b = (2 + a) * b

> let r g = g 3

> let f a b = b (a 1)

এখানে ফাংশনটি fআর্গুমেন্ট হিসাবে দুটি ফাংশন নেয়, 1প্রথম ফাংশনে পাস করে এবং প্রথম কলের ফলাফলটিকে দ্বিতীয় ফাংশনে পাস করে।

কল করতে পারেন আমরা ছিলাম fব্যবহার qএবং rআর্গুমেন্ট হিসাবে, এটা কার্যকরভাবে কাজ করা চাই:

> r (q 1)

যেখানে qপ্রয়োগ করা হবে 1এবং অন্য ফাংশনটি ফেরত দেওয়া হবে (যেমনটি qতত্ক্ষণাতীত); এই ফেরত ফাংশনটি rতার যুক্তি হিসাবে যুক্তি হিসাবে দেওয়া হবে 3। এর ফলাফলটি একটি মান হবে 9

এখন, ধরা যাক আমাদের আরও দুটি ফাংশন ছিল:

> let s a = 3 * a

> let t a = 4 + a

আমরা এইসব পাস পারে fপাশাপাশি এবং একটি মান পেতে 7বা 15, উপর কিনা আমাদের আর্গুমেন্ট ছিল নির্ভর করে s tবা t s। যেহেতু এই ফাংশনগুলি উভয়ই কোনও ফাংশনের পরিবর্তে কোনও মান ফেরত দেয়, তাই কোনও আংশিক প্রয়োগ f s tবা ঘটে না f t s

আমরা লিখেছিলাম তাহলে fসঙ্গে qএবং rআংশিক আবেদন, যেমন পরিবর্তে মনের মধ্যে আমরা একটি ল্যামডা (বেনামী ফাংশন) ব্যবহার করেছেন পারেন:

> let f' a b = b (\x -> a 1 x)

তবে এটি সাধারণতার সীমাবদ্ধ রাখত f'fআর্গুমেন্ট সহ বলা যেতে পারে qএবং rবা sএবং tকিন্তু f'শুধুমাত্র সঙ্গে বলা যেতে পারে qএবং r- f' s tএবং f' t sএকটি ত্রুটি উভয় ফলাফল।

আরও

যদি f'এমন কোনও q'/ r'জুটির সাথে ডাকা হয় যেখানে দু'জনের q'বেশি যুক্তি গ্রহণ q'করা হয় তবে আংশিকভাবে প্রয়োগ করা শেষ হবে f'

বিকল্পভাবে, আপনি অভ্যন্তরের পরিবর্তে qবাইরে মোড়ানো করতে পারেন f, তবে এটি আপনাকে একটি বাজে নেস্ট ল্যাম্বদা দিয়ে ছেড়ে চলে যাবে:

f (\x -> (\y -> q x y)) r

মূলত তরকারীটি qপ্রথম স্থানে কী ছিল!


আপনি আমার চোখ খুললেন। আপনার উত্তর আমাকে অনুধাবন করেছে যে কীভাবে ত্রিযুক্ত / আংশিক প্রয়োগিত ফাংশনগুলি একটি নতুন ফাংশন তৈরির চেয়ে পৃথক যা মূল ফাংশনে আর্গুমেন্টগুলি পাস করে। ১. কার্য়েড / প্যাড ফাংশনগুলির কাছাকাছি যেতে (যেমন চ (কিউ। কুরি (২)) অস্থায়ীভাবে ব্যবহারের জন্য অকারণে পৃথক ফাংশন তৈরি করা বেশি সুক্ষ্ম ((গ্রোভির মতো কার্যকরী ভাষায়))
বিগনেশ্বরান

২. আমার প্রশ্নে আমি বলেছিলাম, "সি তেও আমি একই কাজ করতে পারি।" হ্যাঁ, তবে অ-কার্যকরী ভাষাগুলিতে, যেখানে আপনি ডেটা হিসাবে ফাংশনগুলি অতিক্রম করতে পারবেন না, পৃথক ফাংশন তৈরি করে, যেগুলি প্যারামিটারগুলিকে মূল দিকে এগিয়ে দেয়, কারি / প্যাচনের সমস্ত সুবিধা নেই
বিগনেশ্বরান

আমি লক্ষ্য করেছি যে গ্রোভী হ্যাস্কেল সাধারণীকরণের ধরণটিকে সমর্থন করে না। আমি লিখি ছিল def f = { a, b -> b a.curry(1) }করতে f q, rকাজ করুন এবং def f = { a, b -> b a(1) }বা def f = { a, b -> b a.curry(1)() }জন্য f s, tকাজ করতে। আপনাকে সমস্ত প্যারামিটারগুলি পাস করতে হবে বা স্পষ্টভাবে বলতে হবে যে আপনি কারি করছেন। :(
ভগ্নেশ্বরন

2
@ বিগনেশ্বরান: হ্যাঁ, হাস্কেল এবং তরকারি খুব ভালভাবে একসাথে চলে গেছে তা বলা নিরাপদ । ;] নোট করুন যে হাস্কেল-এ ডিফল্টরূপে ফাংশনগুলি ত্রুটিযুক্ত (সঠিক সংজ্ঞায়) ফাংশন অ্যাপ্লিকেশন নির্দেশ করে, তাই এর f x yঅর্থ অনেকগুলি ভাষা কী লিখবে f(x)(y), নয় f(x, y)। সম্ভবত আপনার কোডটি গ্রোভিতে কাজ করবে যদি আপনি qএমনভাবে লিখেন যাতে এটি লিখিত হয় q(1)(2)?
সিএ ম্যাকক্যান

1
@ উইগনেশ্বরান খুশি আমি সাহায্য করতে পারি! আপনি স্পষ্টভাবে বলতে চেয়েছিলেন যে আপনি আংশিক প্রয়োগ করছেন about ক্লোজুরেতে আমাকে করতে হবে (partial f a b ...)- হাস্কেলের অভ্যস্ত, আমি অন্য ভাষাগুলিতে প্রোগ্রামিং করার সময় অনেকটা সঠিক কারিগরী মিস করি (যদিও আমি সম্প্রতি এফ # তে কাজ করে যাচ্ছি, ধন্যবাদ, এটি সমর্থন করে)।
পল

3

আংশিক প্রয়োগ সম্পর্কে দুটি মূল বিষয় রয়েছে। প্রথমটি সিনট্যাকটিক / সুবিধা - কিছু জেনারেল সংক্ষিপ্ত আকারে পড়তে এবং লিখতে সংক্ষিপ্ত হয়ে যায়, যেমন @ জে কে উল্লেখ করেছেন। (এটি কতটা দুর্দান্ত তা সম্পর্কে আরও জানতে পয়েন্টফ্রি প্রোগ্রামিং পরীক্ষা করে দেখুন!)

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

(:) :: a -> [a] -> [a]

একক যুক্তি গ্রহণ; ফাংশন ধরণের নির্মাণকারীর ->সাহচর্যতার কারণে উপরেরটি সমান:

(:) :: a -> ([a] -> [a])

এটি একটি ফাংশন যা গ্রহণ করে aএবং একটি ফাংশন দেয় [a] -> [a]

এটি আমাদের মত ফাংশন লিখতে দেয়:

($) :: (a -> b) -> a -> b

যা উপযুক্ত ধরণের আর্গুমেন্টে কোনও ফাংশন প্রয়োগ করতে পারে । এমনকি পাগলগুলি:

f :: (t, t1) -> t -> t1 -> (t2 -> t3 -> (t, t1)) -> t2 -> t3 -> [(t, t1)]
f q r s t u v = q : (r, s) : [t u v]

f' :: () -> Char -> (t2 -> t3 -> ((), Char)) -> t2 -> t3 -> [((), Char)]
f' = f $ ((), 'a')  -- <== works fine

ঠিক আছে, তাই এটি একটি স্বীকৃত উদাহরণ ছিল। তবে আরও কার্যকর একটি প্রয়োগকারী ধরণের শ্রেণীর সাথে জড়িত , যার মধ্যে এই পদ্ধতিটি রয়েছে:

(<*>) :: Applicative f => f (a -> b) -> f a -> f b

আপনি দেখতে পাচ্ছেন, প্রকারটি অনুরূপ $যদি আপনি কিছুটা সরিয়ে নেন Applicative f, এবং প্রকৃতপক্ষে, এই শ্রেণিটি একটি প্রসঙ্গে ফাংশন অ্যাপ্লিকেশনটিকে বর্ণনা করে। সুতরাং স্বাভাবিক ফাংশন অ্যাপ্লিকেশন পরিবর্তে:

ghci> map (+3) [1..5]  
[4,5,6,7,8]

আমরা একটি আবেদনকারী প্রসঙ্গে ফাংশন প্রয়োগ করতে পারি; উদাহরণস্বরূপ, সম্ভবত যে প্রসঙ্গে কিছু উপস্থিত বা অনুপস্থিত থাকতে পারে:

ghci> Just map <*> Just (+3) <*> Just [1..5]
Just [4,5,6,7,8]

ghci> Just map <*> Nothing <*> Just [1..5]
Nothing

এখন সত্যিই দুর্দান্ত অংশটি হ'ল আবেদনকারী ধরণের শ্রেণি একাধিক যুক্তির কার্যকারিতা সম্পর্কে কিছুই উল্লেখ করে না - তবুও, এটি তাদের সাথে ডিল করতে পারে এমনকি argu টি যুক্তি যেমন f:

fA' :: Maybe (() -> Char -> (t2 -> t3 -> ((), Char)) -> t2 -> t3 -> [((), Char)])
fA' = Just f <*> Just ((), 'a')

যতদূর আমি জানি, এর সাধারণ আকারে প্রয়োগকারী ধরণের শ্রেণিটি আংশিক প্রয়োগের কিছু ধারণা ছাড়া সম্ভব হবে না। (সেখানকার যে কোনও প্রোগ্রামিং বিশেষজ্ঞের কাছে - দয়া করে আমি ভুল হলে আমাকে সংশোধন করুন!) অবশ্যই, যদি আপনার ভাষার আংশিক প্রয়োগের অভাব থাকে তবে আপনি এটি কোনও আকারে তৈরি করতে পারেন , তবে ... এটি ঠিক একই নয়, তাই না? ? :)


1
Applicativeতরকারী বা আংশিক অ্যাপ্লিকেশন ব্যবহার ছাড়া fzip :: (f a, f b) -> f (a, b)। উচ্চতর অর্ডার ফাংশন সহ একটি ভাষায়, এটি আপনাকে ফান্টারের প্রসঙ্গে কারিঙ এবং আংশিক অ্যাপ্লিকেশনটি তুলতে দেয় এবং এর সমতুল্য (<*>)। উচ্চ-অর্ডার ফাংশন ব্যতীত আপনার কোনও fmapজিনিস থাকবে না যাতে পুরো জিনিসটি অকেজো হয়ে যায়।
সিএ ম্যাকক্যান

প্রতিক্রিয়াটির জন্য ধন্যবাদ ক্যাম্যাকক্যান! আমি জানতাম আমি এই উত্তরটি নিয়ে আমার মাথার উপরে। তাহলে কি আমি ভুল বলেছি?

1
এটা স্পিরিটে সঠিক, অবশ্যই। "সাধারণ ফর্ম", "সম্ভাব্য" এবং "আংশিক প্রয়োগের ধারণার ধারণার" সংজ্ঞা নিয়ে চুল বিভক্ত করা সহজ সত্যটি পরিবর্তন করবে না যে কমনীয় f <$> x <*> yআইডোমেটিক স্টাইলটি সহজেই কাজ করে কারণ কারিটিং এবং আংশিক প্রয়োগ সহজে কাজ করে। অন্য কথায়, এখানে কী সম্ভব তার চেয়ে বেশি আনন্দদায়ক কী গুরুত্বপূর্ণ ।
সিএ ম্যাকক্যান

যতবারই আমি কার্যকরী প্রোগ্রামিংয়ের কোড উদাহরণগুলি দেখি, আমি আরও নিশ্চিত যে এটি একটি বিস্তৃত রসিকতা এবং এটির উপস্থিতি নেই।
কিভেলি

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