ফাংশনাল প্রোগ্রামিংয়ে কীভাবে একটি টাইম ফাংশন বিদ্যমান থাকতে পারে?


646

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

উদাহরণস্বরূপ, এটি বিবেচনা করুন:

f(x,y) = x*x + y; // It is a mathematical function

আপনি যতবার ব্যবহার করুন না কেন f(10,4), এর মান সর্বদা থাকবে 104। যেমন আপনি যেখানেই লিখেছেন না কেন f(10,4), 104সম্পূর্ণ অভিব্যক্তির মান পরিবর্তন না করে আপনি এটিকে প্রতিস্থাপন করতে পারেন । এই সম্পত্তি একটি অভিব্যক্তি রেফারেন্সিয়াল স্বচ্ছতা হিসাবে উল্লেখ করা হয় ।

উইকিপিডিয়া যেমন বলেছে ( লিঙ্ক ),

বিপরীতক্রমে, ফাংশনাল কোডে, একটি ফাংশনের আউটপুট মান কেবলমাত্র যুক্তিগুলির উপর নির্ভর করে যা ফাংশনে ইনপুট হয়, সুতরাং একটি আর্গুমেন্ট x এর জন্য একই মানের সাথে দুবার একটি ফাংশন কল করা একই ফলাফল f (x) উভয় বার উত্পাদন করে।

একটি সময় ফাংশন (যা বর্তমান সময়কে ফিরিয়ে দেয় ) ফাংশনাল প্রোগ্রামিংয়ে থাকতে পারে?

  • যদি হ্যাঁ, তবে এটি কীভাবে থাকতে পারে? এটি কার্যকরী প্রোগ্রামিংয়ের নীতি লঙ্ঘন করে না? এটি বিশেষত রেফারেনশিয়াল স্বচ্ছতা লঙ্ঘন করে যা কার্যকরী প্রোগ্রামিংয়ের অন্যতম সম্পত্তি (যদি আমি এটি সঠিকভাবে বুঝতে পারি)।

  • বা যদি না হয়, তবে কার্যক্ষম প্রোগ্রামিংয়ে বর্তমান সময়ের কীভাবে কেউ জানতে পারবেন?


15
আমি মনে করি বেশিরভাগ (বা সমস্ত) ক্রিয়ামূলক ভাষাগুলি এত কঠোর নয় এবং কার্যকরী এবং অপরিহার্য প্রোগ্রামিংকে একত্রিত করে। কমপক্ষে, এফ # এর থেকে এটি আমার ধারণা।
অ্যালেক্স এফ

13
@ অ্যাডাম: কলকারী প্রথম স্থানটিতে বর্তমান সময়টি কীভাবে জানবে?
নওয়াজ

29
@ অ্যাডাম: আসলে এটি নিখুঁত কার্যকরী ভাষায় অবৈধ (যেমন: অসম্ভব)।
sepp2k

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

12
এফপি সম্পর্কে চিন্তা করার সময় এটি সহজেই ভুলে যাওয়া সহজ: একটি কম্পিউটার হ'ল পরিবর্তনের স্থিতির একটি বিশাল অংশ। এফপি এটি পরিবর্তন করে না, এটি কেবল এটি গোপন করে।
ড্যানিয়েল

উত্তর:


175

এটির ব্যাখ্যা করার আরেকটি উপায় হ'ল: কোনও ক্রিয়াকলাপ বর্তমান সময় পেতে পারে না (যেহেতু এটি পরিবর্তন করে চলে) তবে কোনও ক্রিয়া বর্তমান সময় পেতে পারে। আসুন বলি যে getClockTimeএটি একটি ধ্রুবক (বা একটি নালারী ফাংশন, যদি আপনি চান) যা বর্তমান সময় পাওয়ার ক্রিয়াটি উপস্থাপন করে । এই ক্রিয়াটি প্রতিবার ব্যবহৃত হয় যখন এটি ব্যবহার করা হয় না কেন এটি এটি একটি আসল ধ্রুবক।

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

এখন, আপনি কীভাবে কনসোলে বর্তমান সময়টি মুদ্রণ করতে পারেন? ভাল, আপনি দুটি ক্রিয়া একত্রিত করতে হবে। তাহলে আমরা কীভাবে এটি করতে পারি? আমরা কেবল পাস getClockTimeকরতে পারি না print, যেহেতু মুদ্রণ একটি টাইমস্ট্যাম্পের প্রত্যাশা করে, কোনও ক্রিয়া নয়। তবে আমরা কল্পনা করতে পারি যে সেখানে একজন অপারেটর রয়েছে, >>=যা দুটি ক্রিয়াকে একত্রিত করে, একটি যা টাইমস্ট্যাম্প পায় এবং একটি যা যুক্তি হিসাবে গ্রহণ করে এবং এটি মুদ্রণ করে। পূর্বে উল্লিখিত ক্রিয়াগুলির সাথে এটি প্রয়োগ করা, ফলাফলটি হ'ল ... তদাআ ... একটি নতুন ক্রিয়া যা বর্তমান সময় পেয়ে এটি মুদ্রণ করে। এবং ঘটনাক্রমে হ্যাস্কলে এটি কীভাবে করা হয় ঠিক এটি।

Prelude> System.Time.getClockTime >>= print
Fri Sep  2 01:13:23 東京 (標準時) 2011

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

আমি জানি না এটি অন্যান্য ব্যাখ্যাগুলির তুলনায় আরও পরিষ্কার ছিল কিনা তবে কখনও কখনও এটি আমাকে এইভাবে ভাবতে সহায়তা করে।


33
এটা আমার কাছে বিশ্বাসযোগ্য নয় আপনি সুবিধামত getClockTimeএকটি ফাংশন পরিবর্তে একটি ক্রিয়া কল। ওয়েল, যদি আপনি তা কল, তারপর প্রতি ফাংশন কল কর্ম , তারপর এমনকি অনুজ্ঞাসূচক প্রোগ্রামিং কার্মিক programmming হয়ে যাবে। বা হতে পারে, আপনি একে ক্রিয়াকলাপ প্রোগ্রামিং বলতে চাই ।
নওয়াজ

92
@ নাওয়াজ: এখানে লক্ষ্য করার মূল বিষয়টি হ'ল আপনি কোনও ফাংশনের মধ্যে থেকে কোনও ক্রিয়াকলাপ চালাতে পারবেন না। আপনি নতুন ক্রিয়া করতে কেবল ক্রিয়া এবং ফাংশন একত্রিত করতে পারেন। কোনও ক্রিয়াকলাপ সম্পাদনের একমাত্র উপায় হ'ল এটি আপনার mainক্রিয়ায় রচনা করা । এটি খাঁটি ফাংশনাল কোডটিকে অপরিহার্য কোড থেকে পৃথক করার অনুমতি দেয় এবং এই বিচ্ছেদটি টাইপ সিস্টেম দ্বারা প্রয়োগ করা হয়। প্রথম শ্রেণীর অবজেক্ট হিসাবে ক্রিয়াকলাপের চিকিত্সা আপনাকে এগুলি পাস করার অনুমতি দেয় এবং আপনার নিজের "নিয়ন্ত্রণ কাঠামো" তৈরি করতে দেয় build
হামার

36
হাস্কেলের সমস্ত কিছুই কোনও ক্রিয়াকলাপ নয় - এটি একেবারে বাজে কথা। একটি ফাংশন এমন একটি জিনিস যার প্রকারের মধ্যে একটি রয়েছে ->- মানকটি এই শব্দটিকে কীভাবে সংজ্ঞায়িত করে এবং হ্যাস্কেলের প্রসঙ্গে এটিই একমাত্র বুদ্ধিমান সংজ্ঞা। কিছু যার প্রকার তাই IO Whateverহয় না একটি ফাংশন।
sepp2k

9
@ sepp2k সুতরাং, মাইলিস্ট :: [এ -> বি] একটি ফাংশন? ;)
ফুজ

8
@ থমাসডিংয়ের পরে আমি পার্টিতে সত্যিই দেরি করেছি, তবে আমি কেবল এটি পরিষ্কার করতে চাই: putStrLnএটি কোনও ক্রিয়া নয় - এটি এমন একটি ক্রিয়া যা কোনও ক্রিয়া ফিরিয়ে দেয়getLineএকটি পরিবর্তনশীল যা একটি ক্রিয়া রয়েছে । ক্রিয়াগুলি হ'ল মান, ভেরিয়েবল এবং ফাংশন হ'ল "পাত্রে" / "লেবেল" আমরা সেই ক্রিয়াগুলি দিই।
kqr

356

হ্যা এবং না.

বিভিন্ন কার্যকরী প্রোগ্রামিং ভাষা এগুলিকে আলাদাভাবে সমাধান করে।

হাস্কেলে (খুব খাঁটি একটি) এই সমস্ত জিনিস আই / ও মোনাড নামক কিছুতে ঘটতে হবে - এখানে দেখুন

আপনি এটিকে আপনার ফাংশনে (ওয়ার্ল্ড-স্টেট) অন্য কোনও ইনপুট (এবং আউটপুট) পাওয়া বা স্থান হিসাবে পরিবর্তনের সময় পাওয়ার মতো "অপরিষ্কার" হিসাবে সহজ হিসাবে ভাবতে পারেন।

এফ # এর মতো অন্যান্য ভাষায় কিছু অপরিষ্কারতা অন্তর্নির্মিত থাকে এবং তাই আপনার একটি ফাংশন থাকতে পারে যা একই ইনপুটটির জন্য বিভিন্ন মান দেয় - ঠিক সাধারণ আবশ্যক ভাষাগুলির মতো।

জেফ্রি বুরকা যেমন তাঁর মন্তব্যে উল্লেখ করেছেন: হাস্কেল উইকির সরাসরি আই / ও মোনাডের চমৎকার পরিচয় এখানে ।


223
হাস্কেলের আইও মোনাড সম্পর্কে উপলব্ধি করা গুরুত্বপূর্ণ বিষয়টি হ'ল এই সমস্যাটি ঘুরে দেখার জন্য এটি কেবল একটি হ্যাক নয়; কিছু প্রসঙ্গে ক্রিয়াকলাপগুলির ক্রম সংজ্ঞায়িত করার সমস্যার এক সাধারণ সমাধান মনডস। একটি সম্ভাব্য প্রসঙ্গ হ'ল আসল পৃথিবী, যার জন্য আমাদের কাছে আইও মোনাড রয়েছে। অন্য প্রসঙ্গটি একটি পারমাণবিক লেনদেনের মধ্যে, যার জন্য আমাদের কাছে এসটিএম মনাদ। তবুও অন্য প্রসঙ্গটি একটি খাঁটি ফাংশন হিসাবে একটি প্রসেসরিজাল অ্যালগরিদম (উদাহরণস্বরূপ নুথ শাফল) বাস্তবায়নের মধ্যে রয়েছে, যার জন্য আমাদের কাছে এসটি মোনাদ রয়েছে have এবং আপনি নিজের মনডগুলিও সংজ্ঞায়িত করতে পারেন। মনড একধরণের ওভারলোডযোগ্য সেমিকোলন।
পল জনসন

2
বর্তমান সময় "ফাংশন" পাওয়ার মতো জিনিসগুলি না বলে "প্রক্রিয়া" এর মতো কিছু বলা (যদিও তাত্ক্ষণিকভাবে হাস্কেল সলিউশন এটির ব্যতিক্রম) to
সিঙ্গপোলিমা

হাস্কেল দৃষ্টিকোণ থেকে শাস্ত্রীয় "পদ্ধতিগুলি" ('... -> ()' এর মতো ধরণের জিনিসগুলি) ... -> () এর সাথে খাঁটি ফাংশন হিসাবে কিছুটা ক্ষুদ্র এবং কিছুতেই কিছু করতে পারে না।
কার্স্টেন

3
সাধারণ হাস্কেল শব্দটি হ'ল "ক্রিয়া"।
সেবাস্তিয়ান রেডল

6
"মনড একধরণের ওভারলোডযোগ্য সেমিকোলন" " +1
ব্যবহারকারী 2805751

147

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

data IO a = IO (RealWorld -> (a,RealWorld))

আমরা নিরাপদে আইও ক্রিয়াগুলি প্রয়োগ করতে পারি। এই ধরণের অর্থ: প্রকারের IOএকটি ক্রিয়া একটি ফাংশন, যা এক ধরণের টোকেন নেয় RealWorldএবং ফলাফলের সাথে একটি নতুন টোকেন দেয়।

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

(>>=) :: IO a -> (a -> IO b) -> IO b

>>=একটি ক্রিয়া এবং একটি ক্রিয়া নেয় যা এই ক্রিয়াটির ফলাফল গ্রহণ করে এবং এ থেকে একটি নতুন ক্রিয়া তৈরি করে। রিটার্ন টাইপ হ'ল নতুন ক্রিয়া। উদাহরণস্বরূপ, আসুন সেখানে একটি ফাংশন রয়েছে তা ভান করুন now :: IO String, যা বর্তমান সময়ের প্রতিনিধিত্ব করে একটি স্ট্রিং প্রদান করে। এটি putStrLnমুদ্রণের জন্য আমরা এটি ফাংশন দিয়ে চেইন করতে পারি :

now >>= putStrLn

বা do-Notation এ লিখিত , যা একটি অত্যাবশ্যক প্রোগ্রামার বেশি পরিচিত:

do currTime <- now
   putStrLn currTime

এই সমস্ত খাঁটি, যেমন আমরা RealWorldটোকেনের বাইরের বিশ্ব সম্পর্কে রূপান্তর এবং তথ্য ম্যাপ করি । প্রতিবার, আপনি এই ক্রিয়াটি চালান, আপনি অবশ্যই একটি আলাদা আউটপুট পাবেন, তবে ইনপুটটি এক নয়: RealWorldটোকেনটি আলাদা is


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

2
@ কাইজার.সেস আপনি এমন একটি বিশ্বব্যাপী RealWorldঅবজেক্টের কথা ভাবতে পারেন যা এটি শুরু হওয়ার পরে প্রোগ্রামে চলে যায়।
ফুজ

6
মূলত, আপনার mainফাংশন একটি RealWorldযুক্তি লাগে । শুধু ফাঁসি উপর এটা পাস করা হয়েছে।
লুই ওয়েসারম্যান

13
আপনি দেখুন যে কারণগুলি তারা লুকিয়ে রাখে RealWorldএবং কেবল এটির পরিবর্তনের জন্য শাস্তি ফাংশন সরবরাহ করে putStrLn, তাই কিছু হাস্কেল প্রোগ্রামার তাদের কোনও প্রোগ্রামের RealWorldসাথে পরিবর্তিত হয় না যেমন হাস্কেল কারির ঠিকানা এবং জন্ম তারিখ এমন হয় যে তারা পাশের প্রতিবেশী হয়ে ওঠে বড় হওয়া (এটি হ্যাস্কেল প্রোগ্রামিং ভাষার ক্ষতি করতে এমনভাবে সময়-স্থানের ধারাবাহিকতার ক্ষতি করতে পারে))
পাইরুলেজ

2
RealWorld -> (a, RealWorld) সম্মতিসূত্রীর অধীনে এমনকি রূপক হিসাবে ভেঙে যায় না, যতক্ষণ না আপনি মনে রাখবেন যে আসল পৃথিবী সর্বদা আপনার ফাংশনের (বা আপনার বর্তমান প্রক্রিয়া) বাইরে মহাবিশ্বের অন্যান্য অংশ দ্বারা পরিবর্তিত হতে পারে। সুতরাং (ক) রূপকটি ভেঙে যায় না এবং (খ) প্রতিবার যে RealWorldধরণের মান যেমন তার ফাংশনে প্রেরণ করা হয় ততক্ষণ ফাংশনটির পুনরায় মূল্যায়ন করতে হবে, কারণ এর মধ্যে আসল পৃথিবী পরিবর্তিত হবে ( @ ফুজ বর্ণিত হিসাবে এটিকে মডেল করা হয়, প্রতিবার আমরা যখন সত্যিকারের বিশ্বের সাথে যোগাযোগ করি তখন একটি আলাদা 'টোকেন মান' ফিরিয়ে দেয়)।
কিউকিউইউ

73

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

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

ক্লিন এ এটি একটি ফাংশন হবে তবে ফাংশনটি তার যুক্তি হিসাবে একটি বিশ্ব মূল্য গ্রহণ করবে এবং এর ফলাফল হিসাবে একটি নতুন বিশ্বের মান (বর্তমান সময়ের পাশাপাশি) প্রদান করবে। প্রকারের সিস্টেমটি নিশ্চিত করবে যে প্রতিটি বিশ্বের মান কেবল একবার ব্যবহার করা যেতে পারে (এবং প্রতিটি ক্রিয়াকলাপ যা একটি মান মূল্য গ্রহন করে একটি নতুন উত্পন্ন করে)। এইভাবে সময় ফাংশনটি প্রতিবারই আলাদা যুক্তি দিয়ে ডাকতে হবে এবং এভাবে প্রতিবারই আলাদা সময় ফিরতে দেওয়া হবে।


2
এটি এটিকে শোনায় যেন হাসেল এবং ক্লিন বিভিন্ন কাজ করে। আমি যা বুঝতে পেরেছি, সেগুলি থেকে তারা একই কাজ করে, হেস্কেল এটি সম্পাদন করার জন্য একটি সুন্দর সিনট্যাক্স (?) সরবরাহ করে।
কনরাড রুডলফ

27
@ কনরাড: তারা এই অর্থে একই কাজ করে যে উভয়ই বিমূর্ত পার্শ্ব প্রতিক্রিয়াগুলির জন্য টাইপ সিস্টেম বৈশিষ্ট্যগুলি ব্যবহার করে তবে এটি প্রায় about মনে রাখবেন যে আইও মনাদকে একটি বিশ্বের ধরণের দিক দিয়ে ব্যাখ্যা করা খুব ভাল, তবে হাস্কেল স্ট্যান্ডার্ডটি আসলে কোনও বিশ্ব প্রকারের সংজ্ঞা দেয় না এবং হাসকেলে ওয়ার্ল্ড টাইপের কোনও মূল্য পাওয়া সম্ভব নয় (যদিও এটি খুব সম্ভব এবং প্রকৃতপক্ষে) পরিষ্কার মধ্যে প্রয়োজনীয়)। আরও হ্যাস্কেলের কোনও টাইপ সিস্টেম বৈশিষ্ট্য হিসাবে স্বতন্ত্রতা টাইপিং নেই, সুতরাং এটি যদি আপনাকে একটি ওয়ার্ল্ড অ্যাক্সেস দেয় তবে এটি নিশ্চিত করতে পারে না যে আপনি এটি পরিষ্কারের মতো খাঁটি উপায়ে ব্যবহার করেছেন।
sepp2k

51

"বর্তমান সময়" কোনও ফাংশন নয়। এটি একটি প্যারামিটার। যদি আপনার কোডটি বর্তমান সময়ের উপর নির্ভর করে তবে এর অর্থ আপনার কোডটি সময়ের সাথে প্যারামিটারাইজড।


22

এটি সম্পূর্ণরূপে খাঁটি কার্যকরী উপায়ে করা যেতে পারে। এটি করার বিভিন্ন উপায় রয়েছে তবে সবচেয়ে সহজ হ'ল সময় ফাংশনটি কেবল সময় নয় কেবল ফিরে আসে পরবর্তী সময় পরিমাপের জন্য আপনাকে অবশ্যই ফাংশনটি কল করতে হবে

সি # তে আপনি এটি এর প্রয়োগ করতে পারেন:

// Exposes mutable time as immutable time (poorly, to illustrate by example)
// Although the insides are mutable, the exposed surface is immutable.
public class ClockStamp {
    public static readonly ClockStamp ProgramStartTime = new ClockStamp();
    public readonly DateTime Time;
    private ClockStamp _next;

    private ClockStamp() {
        this.Time = DateTime.Now;
    }
    public ClockStamp NextMeasurement() {
        if (this._next == null) this._next = new ClockStamp();
        return this._next;
    }
}

(মনে রাখবেন যে এটি একটি উদাহরণ যা সাধারণ বোঝার জন্য ব্যবহারিক নয়।

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

// Immutable. A result accompanied by a clockstamp
public struct TimeStampedValue<T> {
    public readonly ClockStamp Time;
    public readonly T Value;
    public TimeStampedValue(ClockStamp time, T value) {
        this.Time = time;
        this.Value = value;
    }
}

// Times an empty loop.
public static TimeStampedValue<TimeSpan> TimeALoop(ClockStamp lastMeasurement) {
    var start = lastMeasurement.NextMeasurement();
    for (var i = 0; i < 10000000; i++) {
    }
    var end = start.NextMeasurement();
    var duration = end.Time - start.Time;
    return new TimeStampedValue<TimeSpan>(end, duration);
}

public static void Main(String[] args) {
    var clock = ClockStamp.ProgramStartTime;
    var r = TimeALoop(clock);
    var duration = r.Value; //the result
    clock = r.Time; //must now use returned clock, to avoid seeing old measurements
}

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


আকর্ষণীয়, তবে i++
লুপটির

@ snim2 আমি নিখুঁত নই : পি এই বিষয়টিকে স্বচ্ছন্দ করুন যে নোংরা পরিবর্তনের ফলে ফলাফলের রেফারেন্সিয়াল স্বচ্ছতা প্রভাবিত হয় না। যদি আপনি একই 'লাস্টম্যাসমেন্টমেন্ট' দু'বারে পাস করেন তবে আপনি পরের পরবর্তী পরিমাপটি পাবেন এবং একই ফলস্বরূপ ফিরে আসবেন।
ক্রেগ গিডনি

@ স্ট্রিল্যাঙ্ক এর জন্য ধন্যবাদ। আমি আবশ্যক কোডে ভাবি, সুতরাং কার্যকরী ধারণাটি এভাবে ব্যাখ্যা করা দেখতে আকর্ষণীয়। আমি তখন এমন কোনও ভাষা কল্পনা করতে পারি যেখানে এই প্রাকৃতিক এবং সিনট্যাক্টিক্যালি ক্লিনার।
ডাব্লুডাব্লু

আপনি প্রকৃতপক্ষে সি # তে মোনাডে যেতে পারেন, এভাবে সময় স্ট্যাম্পের স্পষ্টভাবে পাসিং এড়ানো। আপনার মতো কিছু দরকার struct TimeKleisli<Arg, Res> { private delegate Res(TimeStampedValue<Arg>); }। তবে এর সাথে কোডটি doসিনট্যাক্সের সাথে হাস্কেলের মতো দুর্দান্ত দেখাচ্ছে না ।

@ লেফট্রাউন্ডেবাট আপনি সি # তে একটি মোনাড রয়েছে বলে ডাকে এমন পদ্ধতি হিসাবে বাইন্ড ফাংশন প্রয়োগ করে প্রয়োগ করে SelectManyযা ক্যোয়ারী বোধগম্য বাক্য গঠনটিকে সক্ষম করে। আপনি এখনও মনডের উপর দিয়ে বহুবিধভাবে প্রোগ্রাম করতে পারবেন না, সুতরাং এটি দুর্বল টাইপ সিস্টেমের বিরুদ্ধে সমস্ত উত্সাহী লড়াই :(
সারা

16

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

প্রতিক্রিয়াশীল ফাংশনাল প্রোগ্রামিংয়ের এটি একটি আলোচিত বিষয়। আপনি যদি এই ধরণের জিনিসগুলিতে আগ্রহী হন তবে এটি পড়ুন: http://digitalcommons.ohsu.edu/csetech/91/ (২৮ পৃষ্ঠা)


3
এবং কীভাবে এই প্রশ্নের সাথে সম্পর্কিত?
নওয়াজ

5
আপনার প্রশ্নটি সময় নির্ভর নির্ভর আচরণকে খাঁটি কার্যকরী উপায়ে মডেলিং সম্পর্কে ছিল, উদাহরণস্বরূপ, এমন একটি ফাংশন যা বর্তমান সিস্টেমের ঘড়িকে ফিরিয়ে দেয়। আপনি সেই অবস্থায় অ্যাক্সেস পেতে সমস্ত কার্য এবং তাদের নির্ভরতা গাছের মাধ্যমে আইও মনডের সমতুল্য কিছু থ্রেড করতে পারেন; অথবা আপনি পর্যবেক্ষণের নিয়মগুলি গঠনমূলক নিয়মের পরিবর্তে সংজ্ঞায়িত করে রাজ্যটিকে মডেল করতে পারেন। এই কেন জটিল রাষ্ট্র মডেলিং হয় inductively কার্যকরী প্রোগ্রামিং যাতে অপ্রাকৃত বলে মনে হয়, কারণ লুকানো রাষ্ট্র সত্যিই একটি হল coinductive সম্পত্তি।
জেফ্রি আগুয়েলেরা

দুর্দান্ত উত্স! সাম্প্রতিক কিছু আছে কি? জেএস সম্প্রদায়টি এখনও স্ট্রিম ডেটা বিমূর্তিগুলির সাথে লড়াই করছে বলে মনে হচ্ছে।
দিমিত্রি জইতসেভ

12

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


11

হ্যাঁ! আপনি সঠিক! এখন () বা কারেন্টটাইম () বা এই জাতীয় স্বাদের কোনও পদ্ধতির স্বাক্ষর এক উপায়ে রেফারেন্সিয়াল স্বচ্ছতা প্রদর্শন করছে না। কিন্তু সংকলককে নির্দেশ দিয়ে এটি একটি সিস্টেম ক্লক ইনপুট দ্বারা প্যারামিটারাইজড।

আউটপুট দ্বারা, এখন () সম্ভবত উল্লেখযোগ্য স্বচ্ছতার অনুসরণ না করার মতো দেখাচ্ছে like তবে সিস্টেমের ঘড়ির আসল আচরণ এবং এর উপরে থাকা ফাংশনটি রেফারেন্সিয়াল স্বচ্ছতা মেনে চলে।


11

হ্যাঁ, অপরিষ্কার ফাংশনাল প্রোগ্রামিং (ডিফল্ট বা মূলটি হ'ল খাঁটি ফাংশনাল প্রোগ্রামিং) হিসাবে পরিচিত ফাংশনাল প্রোগ্রামিংয়ের সামান্য পরিবর্তিত সংস্করণ ব্যবহার করে ফাংশনাল প্রোগ্রামিংয়ে একটি গেমিং টাইম ফাংশন উপস্থিত থাকতে পারে।

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

কয়েকটি ফাংশনাল প্রোগ্রামিং প্রোগ্রামিং ল্যাঙ্গুয়েজে এই অপরিষ্কার বৈশিষ্ট্য অন্তর্নির্মিত রয়েছে যাতে কোন কোডটি অপরিষ্কার এবং কোনটি খাঁটি (যেমন F #, ইত্যাদি) আলাদা করা সহজ নয় এবং কিছু কার্যকরী প্রোগ্রামিং ল্যাঙ্গুয়েজ নিশ্চিত করে যে আপনি যখন কিছু অপরিষ্কার স্টাফ করেন তখন হাসেল এর মতো খাঁটি কোডের তুলনায় সেই কোডটি স্পষ্টতই আলাদা।

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


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

1
@ আঙ্কুর: এটি ঠিক একই জিনিস। প্রোগ্রামটি যদি কেবল নিজের থেকে বাদ দিয়ে অন্য কোনও কিছুর সাথে ইন্টারঅ্যাক্ট করে (যেমন তাদের কীবোর্ডের মাধ্যমে বিশ্ব, সুতরাং কথা বলার জন্য) এটি এখনও অপরিষ্কার।
পরিচয়

1
@ আঙ্কুর: হ্যাঁ, আমি মনে করি আপনি ঠিক বলেছেন! যদিও কমান্ড লাইনে বৃহত ইনপুট ডেটা প্রেরণ করা খুব ব্যবহারিক নাও হতে পারে, এটি এটি করার খাঁটি উপায় হতে পারে।
জর্জিও

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

4
@ জিগিস্টার - "ওয়ার্ল্ড অবজেক্ট" আসলে কিছুই অন্তর্ভুক্ত করে না - এটি কেবল প্রোগ্রামের বাইরে বিশ্বের পরিবর্তিত রাষ্ট্রের জন্য প্রক্সি। এর একমাত্র উদ্দেশ্য হ'ল সুস্পষ্টভাবে এমনভাবে চিহ্নিত করতে হবে যাতে টাইপ সিস্টেম এটি সনাক্ত করতে পারে।
ক্রিস নট্টি কম্বে

7

আপনার প্রশ্নটি একটি কম্পিউটার ভাষার দুটি সম্পর্কিত পদক্ষেপের সাথে সম্পর্কিত: ক্রিয়ামূলক / অপরিহার্য এবং খাঁটি / অশুদ্ধ।

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

একটি খাঁটি ভাষা পার্শ্ব প্রতিক্রিয়া তৈরি করে না বা নির্ভর করে না এবং একটি অপরিষ্কার ভাষা সেগুলি জুড়ে ব্যবহার করে।

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

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

-- this is a pure function, written in functional style.
fib 0 = 0
fib 1 = 1
fib n = fib (n-1) + fib (n-2)

-- This is an impure wrapper around the pure function, written in imperative style
-- It depends on inputs and produces outputs.
main = do
    putStrLn "Please enter the input parameter"
    inputStr <- readLine
    putStrLn "Starting time:"
    getCurrentTime >>= print
    let inputInt = read inputStr    -- this line is pure
    let result = fib inputInt       -- this is also pure
    putStrLn "Result:"
    print result
    putStrLn "Ending time:"
    getCurrentTime >>= print

4
আপনি যদি সময় পাওয়ার সুনির্দিষ্ট সমস্যাটি সমাধান করতে পারেন এবং আমরা কতটা IOমূল্যবোধ এবং ফলাফলকে খাঁটি বিবেচনা করি সে সম্পর্কে কিছুটা ব্যাখ্যা করলে এটি সহায়ক হবে ।
অ্যান্ড্রুসি

আসলে, এমনকি 100% খাঁটি প্রোগ্রামগুলি সিপিইউকে উত্তাপ দেয় যা একটি পার্শ্ব-প্রতিক্রিয়া।
জার্গ ডব্লু মিট্টাগ

3

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

উদাহরণস্বরূপ হাস্কেল রানটাইম আমাকে কল করা একটি ক্রিয়া সংজ্ঞায়িত করবে বলে প্রত্যাশা করে main করব যা আমার প্রোগ্রামটি তৈরি করে এমন সমস্ত ক্রিয়াকে নিয়ে গঠিত def রানটাইম এরপরে এই ক্রিয়াটি কার্যকর করে। বেশিরভাগ সময়, এটি করার সময় এটি খাঁটি কোড কার্যকর করে। সময়ে সময়ে রানটাইম I / O সঞ্চালনের জন্য গণিত ডেটা ব্যবহার করবে এবং বিশুদ্ধ কোডে ফিরে ডেটা ফিড করবে।

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

উদাহরণ: clock_t c = time(NULL); printf("%d\n", c + 2);সি-তে, বনাম main = getCPUTime >>= \c -> print (c + 2*1000*1000*1000*1000)। হাস্কেল ke অপারেটরটি >>=ক্রিয়া রচনা করতে ব্যবহৃত হয়, প্রথমটির ফলাফলটিকে দ্বিতীয় কার্যের ফলে একটি ফাংশনে প্রথম স্থানান্তর করে। দেখতে বেশ তীব্র, হাস্কেল সংকলকগুলি সিনট্যাকটিক চিনির সমর্থন করে যা আমাদের নিম্নোক্ত কোডটি নিম্নরূপে লিখতে দেয়:

type Clock = Integer -- To make it more similar to the C code

-- An action that returns nothing, but might do something
main :: IO ()
main = do
    -- An action that returns an Integer, which we view as CPU Clock values
    c <- getCPUTime :: IO Clock
    -- An action that prints data, but returns nothing
    print (c + 2*1000*1000*1000*1000) :: IO ()

পরেরটি বেশ জরুরী মনে হচ্ছে, তাই না?


1

যদি হ্যাঁ, তবে এটি কীভাবে থাকতে পারে? এটি কার্যকরী প্রোগ্রামিংয়ের নীতি লঙ্ঘন করে না? এটি বিশেষত রেফারেনশিয়াল স্বচ্ছতা লঙ্ঘন করে

এটি বিশুদ্ধভাবে কার্যকরী অর্থে বিদ্যমান নেই।

বা যদি না হয়, তবে কার্যক্ষম প্রোগ্রামিংয়ে বর্তমান সময়ের কীভাবে কেউ জানতে পারবেন?

কম্পিউটারে একটি সময় কীভাবে পুনরুদ্ধার করা হয় তা প্রথমে জেনে রাখা কার্যকর হতে পারে। মূলত সেখানে অনবোর্ড সার্কিটরি রয়েছে যা সময়কে লক্ষ্য রাখে (যে কারণে কম্পিউটারে সাধারণত একটি ছোট সেল ব্যাটারির প্রয়োজন হয়)। তারপরে এমন কিছু অভ্যন্তরীণ প্রক্রিয়া থাকতে পারে যা একটি নির্দিষ্ট মেমরির রেজিস্টারে সময়টির মূল্য নির্ধারণ করে। যা সিপিইউ দ্বারা পুনরুদ্ধার করা যেতে পারে এমন কোনও মানটিতে মূলত সিদ্ধ হয়।


হাস্কেলের জন্য, একটি 'আইও অ্যাকশন' ধারণা রয়েছে যা এমন এক ধরণের প্রতিনিধিত্ব করে যা কিছু আইও প্রক্রিয়া চালিয়ে যেতে পারে। সুতরাং কোনও timeমান উল্লেখ করার পরিবর্তে আমরা একটি IO Timeমান উল্লেখ করি । এই সমস্ত নিখুঁত ক্রিয়ামূলক হবে। 'সময় নিবন্ধের মান পড়ুন' এর আওতায় আমরা timeকিছু উল্লেখ করছি না

আমরা যখন হাস্কেল প্রোগ্রামটি বাস্তবায়িত করি তখন আইও অ্যাকশনটি আসলে ঘটত।

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