যদি ফাংশনাল প্রোগ্রামিং ল্যাঙ্গুয়েজগুলি কোনও রাজ্যকে সংরক্ষণ করতে না পারে, তবে তারা কীভাবে কোনও সাধারণ জিনিস যেমন কোনও ব্যবহারকারীর কাছ থেকে ইনপুট পড়তে পারে (তার মানে তারা কীভাবে এটি "সঞ্চয়" করে) বা এই বিষয়ে কোনও ডেটা সংরক্ষণ করে?
আপনি জড়ো হওয়ার সাথে সাথে ক্রিয়ামূলক প্রোগ্রামিংয়ের স্টেট থাকে না। তবে এর অর্থ এই নয় যে এটি ডেটা সঞ্চয় করতে পারে না। পার্থক্যটি হ'ল আমি যদি লাইনের পাশাপাশি একটি (হাস্কেল) বিবৃতি লিখি
let x = func value 3.14 20 "random"
in ...
আমি গ্যারান্টিযুক্ত যে এর মান x
সর্বদা একই থাকে ...
: কোনও কিছুই সম্ভবত এটি পরিবর্তন করতে পারে না। একইভাবে, যদি আমার কোনও ফাংশন থাকে f :: String -> Integer
(একটি ফাংশন স্ট্রিং গ্রহণ করে এবং পূর্ণসংখ্যা ফেরত দেয়) তবে আমি নিশ্চিত হতে পারি যে f
এটির যুক্তিটি সংশোধন করবে না, বা কোনও বিশ্বব্যাপী ভেরিয়েবল পরিবর্তন করবে না, বা কোনও ফাইলে ডেটা লিখবে, ইত্যাদি। যেমনটি সিপ্প 2 কে উপরের মন্তব্যে বলেছে, এই অ-পরিবর্তনশীলতা প্রোগ্রামগুলি সম্পর্কে যুক্তি দেখানোর জন্য সত্যই সহায়ক: আপনি এমন ফাংশনগুলি লিখুন যা আপনার ডেটা ভাঁজ করে, টুকরো টুকরো করে এবং বিকৃত করে, নতুন কপিগুলি ফিরিয়ে দেয় যাতে আপনি তাদের একসাথে শৃঙ্খলাবদ্ধ করতে পারেন, এবং আপনি নিশ্চিত হতে পারেন যে কোনওটিই নয় এই ফাংশন কলগুলির মধ্যে "ক্ষতিকারক" কিছু করতে পারে। আপনি জানেন যে x
সর্বদা হয় x
, এবং আপনাকে উদ্বিগ্ন হওয়ার দরকার নেই যে কেউ x := foo bar
ঘোষণার মধ্যে কোথাও কোথাও লিখেছেনx
এবং এর ব্যবহার, কারণ এটি অসম্ভব।
এখন, যদি আমি কোনও ব্যবহারকারীর কাছ থেকে ইনপুট পড়তে চাই? কেনেনিটিএম যেমন বলেছিল, ধারণাটি এই যে অশুচি ফাংশনটি একটি খাঁটি ফাংশন যা পুরো বিশ্বকে তর্ক হিসাবে পরিণত করে, এবং এর ফলাফল এবং বিশ্ব উভয়কেই ফিরিয়ে দেয়। অবশ্যই, আপনি আসলে এটি করতে চান না: একটি জিনিসের জন্য, এটি মারাত্মকভাবে ছদ্মবেশী এবং অন্যটির জন্য, যদি আমি একই বিশ্বের বিষয়টিকে পুনরায় ব্যবহার করি তবে কী ঘটে? সুতরাং এটি একরকম বিমূর্ত হয়। হাসেল আইও টাইপ দিয়ে এটি পরিচালনা করে:
main :: IO ()
main = do str <- getLine
let no = fst . head $ reads str :: Integer
...
এটি আমাদের জানায় যে main
এটি একটি আইও ক্রিয়া যা কোনও কিছুই প্রত্যাবর্তন করে না; এই অ্যাকশনটি কার্যকর করা হ্যাসেল প্রোগ্রাম চালানোর অর্থ। নিয়মটি হল যে আইও প্রকারগুলি কখনই আইও ক্রিয়া থেকে বাঁচতে পারে না; এই প্রসঙ্গে, আমরা ব্যবহার করে সেই ক্রিয়াটি প্রবর্তন করি do
। সুতরাং, getLine
একটি প্রদান করে IO String
, যা দুটি উপায়ে চিন্তা করা যায়: প্রথমত, একটি ক্রিয়া হিসাবে, যা যখন চালানো হয়, একটি স্ট্রিং উত্পাদন করে; দ্বিতীয়ত, স্ট্রিং হিসাবে এটি আইও দ্বারা "কলঙ্কিত" যেহেতু এটি অশুচিভাবে প্রাপ্ত হয়েছিল। প্রথমটি আরও সঠিক, তবে দ্বিতীয়টি আরও সহায়ক হতে পারে। <-
লাগে String
আউট IO String
এবং এটি দোকানে str
-কিন্তু যেহেতু আমরা একটি আই ক্রিয়াটি, আমরা এটা ব্যাক আপ মোড়ানো, তাই এটি "এস্কেপ" করতে পারেন না আছে। পরবর্তী লাইনটি একটি পূর্ণসংখ্যা পড়ার চেষ্টা করে ( reads
) এবং প্রথম সফল ম্যাচটি ধরে ফেলে (fst . head
); এটি সমস্ত খাঁটি (কোনও আইও নয়), তাই আমরা এটির সাথে একটি নাম দেব let no = ...
। আমরা তখন উভয় ব্যবহার করতে পারেন no
এবং str
এ ...
। আমরা এইভাবে অপবিত্র ডেটা সংরক্ষণ করেছেন (থেকে getLine
মধ্যে str
) এবং বিশুদ্ধ তথ্য ( let no = ...
)।
আইওর সাথে কাজ করার জন্য এই প্রক্রিয়াটি খুব শক্তিশালী: এটি আপনাকে আপনার প্রোগ্রামের খাঁটি, অ্যালগোরিদমিক অংশটিকে অপরিষ্কার, ব্যবহারকারী-মিথস্ক্রিয়া পক্ষ থেকে পৃথক করতে এবং টাইপ স্তরে এটি প্রয়োগ করতে দেয়। আপনার minimumSpanningTree
ফাংশন সম্ভবত আপনার কোডের অন্য কোনও কিছু পরিবর্তন করতে পারে না, বা আপনার ব্যবহারকারীর কাছে একটি বার্তা লিখতে পারে না ইত্যাদি। এটা নিরাপদ.
হাস্কেলের আইও ব্যবহার করার জন্য আপনার যা যা জানা দরকার তা হ'ল; যদি আপনি চান তবে আপনি এখানে থামতে পারেন। তবে এটি কেন কাজ করে তা যদি আপনি বুঝতে চান তবে পড়া চালিয়ে যান। (এবং দ্রষ্টব্য যে এই জিনিসটি হাস্কেলের সাথে নির্দিষ্ট হবে — অন্যান্য ভাষাগুলি আলাদা প্রয়োগ করতে পারে))
সুতরাং এটি সম্ভবত কিছুটা প্রতারণার মতো মনে হয়েছিল, একরকম খাঁটি হাস্কেলের সাথে অশুচিতা যুক্ত করেছে। তবে এটি নয় - এটি প্রমাণিত হয়েছে যে আমরা আইও টাইপটি পুরোপুরি খাঁটি হাস্কেলের মধ্যে প্রয়োগ করতে পারি (যতক্ষণ না আমাদের দেওয়া হয় RealWorld
)। ধারণাটি হ'ল: একটি আইও ক্রিয়া IO type
একটি ফাংশন হিসাবে একই RealWorld -> (type, RealWorld)
, যা আসল পৃথিবী নেয় এবং প্রকারের কোনও বস্তু type
এবং সংশোধিত উভয়কেই ফিরিয়ে দেয় RealWorld
। তারপরে আমরা কয়েকটি ফাংশন সংজ্ঞায়িত করি যাতে আমরা উন্মাদ না হয়ে এই ধরণের ব্যবহার করতে পারি:
return :: a -> IO a
return a = \rw -> (a,rw)
(>>=) :: IO a -> (a -> IO b) -> IO b
ioa >>= fn = \rw -> let (a,rw') = ioa rw in fn a rw'
প্রথম এক আমাদের আই কর্ম যা কিছু করবেন না কথা বলার জন্য অনুমতি দেয়: return 3
একটি আই কর্ম যা বাস্তব জগতে এবং মাত্র আয় অনুসন্ধান করে না 3
। >>=
অপারেটর, উচ্চারিত "বেঁধে", আমাদের আই কর্ম চালানোর জন্য অনুমতি দেয়। এটি আইও অ্যাকশন থেকে মানটি বের করে, ফাংশনটির মাধ্যমে এটি এবং বাস্তব জগতকে পাস করে এবং ফলস্বরূপ আইও অ্যাকশনটি প্রদান করে। নোট করুন যে >>=
আমাদের বিধি কার্যকর করে যে আইও ক্রিয়াকলাপগুলির ফলাফলকে কখনই এড়াতে দেওয়া হয় না।
এরপরে আমরা main
উপরেরটিকে ফাংশন অ্যাপ্লিকেশনগুলির নিম্নলিখিত সাধারণ সেটটিতে রূপান্তর করতে পারি :
main = getLine >>= \str -> let no = (fst . head $ reads str :: Integer) in ...
main
প্রাথমিকের সাথে হাস্কেল রানটাইম জাম্প-শুরু হয় RealWorld
, এবং আমরা প্রস্তুত হয়েছি! সবকিছু খাঁটি, এটিতে একটি অভিনব বাক্য গঠন রয়েছে।
[ সম্পাদনা: @ কনোনাল হিসাবে উল্লেখ করা হয়েছে , হাস্কেল আইও করার জন্য এটি ব্যবহার করে না। এই মডেলটি যদি আপনি একযোগে যুক্ত হন বা সত্যিই কোনও আইও অ্যাকশনের মাঝামাঝি বিশ্বের কোনও উপায় যুক্ত করেন তবে এই মডেলটি ভেঙে যায়, সুতরাং হাস্কেলের পক্ষে এই মডেলটি ব্যবহার করা অসম্ভব। এটি কেবলমাত্র অনুক্রমিক গণনার জন্য সঠিক। সুতরাং, এটি হতে পারে যে হাস্কেলের আইও কিছুটা ডজ; এটি না হলেও এটি অবশ্যই এই মার্জিত নয় leg কনল এর পর্যবেক্ষণ অনুসারে, অজওয়ার্ড স্কোয়াড [পিডিএফ] , ৩.১ বিভাগে সামলাতে সাইমন পাইটন-জোনস কী বলেছে তা দেখুন ; তিনি এই লাইনের পাশাপাশি কোনও বিকল্প মডেলের পরিমাণ কী হতে পারে তা উপস্থাপন করেন তবে তার জটিলতার জন্য এটিকে ফেলে দেন এবং আলাদা ট্যাক্স নেন]]
আবার, এটি ব্যাখ্যা করে (বেশ অনেকখানি) কীভাবে আইও, এবং সাধারণভাবে পরিব্যক্তি হ্যাসকেলে কাজ করে; আপনি যদি জানতে চান এটি যদি এই হয় তবে আপনি এখানে পড়া বন্ধ করতে পারেন। আপনি যদি তত্ত্বের একটি শেষ ডোজ চান, পড়তে থাকুন — তবে মনে রাখবেন, এই মুহুর্তে, আমরা আপনার প্রশ্ন থেকে সত্যিই অনেক দূরে চলে গেছি!
সুতরাং একটি শেষ জিনিস: এটি এই কাঠামোটি সক্রিয় করে - একটি প্যারাম্যাট্রিক টাইপ return
এবং >>=
- খুব সাধারণ; এটি একটি একসংখ্যা বলা হয়, এবং do
স্বরলিপি, return
এবং >>=
তাদের সাথে হবে। আপনি যেমন এখানে দেখেছেন, মনদেহগুলি যাদু নয়; যাদুকর সব যে do
ব্লকগুলি ফাংশন কলগুলিতে পরিণত হয়। RealWorld
টাইপ একমাত্র জায়গা আমরা কোনো জাদু দেখতে হয়। প্রকারের মতো []
, তালিকার নির্মাণকারী, এছাড়াও মনড এবং তাদের অপরিষ্কার কোডের সাথে কোনও সম্পর্ক নেই।
আপনি এখন (প্রায়) একটি মনাদ ধারণা সম্পর্কে কিছু জানেন (কয়েকটি আইন যা সন্তুষ্ট হতে হবে এবং আনুষ্ঠানিক গাণিতিক সংজ্ঞা ব্যতীত) তবে আপনার অন্তর্দৃষ্টিটির অভাব রয়েছে। অনলাইনে মোনাদ টিউটোরিয়ালগুলির একটি হাস্যকর সংখ্যা রয়েছে; আমি চাই এই এক , কিন্তু আপনি অপশন আছে। তবে এটি সম্ভবত আপনাকে সাহায্য করবে না ; স্বজ্ঞাততা লাভের একমাত্র আসল উপায় হ'ল এগুলি ব্যবহার এবং সঠিক সময়ে কয়েকটি টিউটোরিয়াল পড়ার সংমিশ্রণের মাধ্যমে।
যাইহোক, আইও বোঝার জন্য আপনার এই অন্তর্দৃষ্টি দরকার নেই । পূর্ণ সাধারণতার মধ্যে মোনাডগুলি বোঝা কেকের উপরে আইসিং দিচ্ছে, তবে আপনি এখনই আইও ব্যবহার করতে পারেন। আমি আপনাকে প্রথম main
ফাংশনটি দেখানোর পরে আপনি এটি ব্যবহার করতে পারেন । এমনকি আপনি আইও কোডটিকে এমনভাবে আচরণ করতে পারেন যেন এটি একটি অপরিষ্কার ভাষায়! তবে মনে রাখবেন যে অন্তর্নিহিত কার্যক্ষম প্রতিনিধিত্ব রয়েছে: কারও প্রতারণা।
(পিএস: দৈর্ঘ্যের জন্য দুঃখিত। আমি কিছুটা দূরে চলে এসেছি))