হাস্কেল টাইপ বনাম ডেটা কনস্ট্রাক্টর


124

আমি শেখ্যুআহসকল ডটকম থেকে হাস্কেল শিখছি । টাইপ কনস্ট্রাক্টর এবং ডেটা কনস্ট্রাক্টর বুঝতে আমার সমস্যা হচ্ছে। উদাহরণস্বরূপ, আমি এর মধ্যে পার্থক্যটি সত্যই বুঝতে পারি না:

data Car = Car { company :: String  
               , model :: String  
               , year :: Int  
               } deriving (Show) 

এবং এই:

data Car a b c = Car { company :: a  
                     , model :: b  
                     , year :: c   
                     } deriving (Show)  

আমি বুঝতে পারি যে প্রথমটি Carটাইপের ডেটা তৈরির জন্য কেবল একটি কনস্ট্রাক্টর ( ) ব্যবহার করে Car। আমি সত্যিই দ্বিতীয়টি বুঝতে পারি না।

এছাড়াও, কীভাবে ডেটা প্রকারগুলি এর মতো সংজ্ঞায়িত করা হয়:

data Color = Blue | Green | Red

এই সব মধ্যে ফিট?

আমি যা বুঝতে থেকে, তৃতীয় উদাহরণটি ( Color:) একটি টাইপ যা তিন রাজ্যে হতে পারে Blue, Greenবা Red। তবে আমি প্রথম দুটি উদাহরণকে কীভাবে বুঝি তার সাথে এই দ্বন্দ্ব রয়েছে: এই ধরণেরটি Carকেবলমাত্র একটি রাজ্যেই থাকতে পারে Car, যা বিভিন্ন পরামিতি তৈরি করতে পারে? যদি তা হয় তবে দ্বিতীয় উদাহরণটি কীভাবে মাপসই হয়?

মূলত, আমি একটি ব্যাখ্যা খুঁজছি যা উপরোক্ত তিনটি কোড উদাহরণ / নির্মাণকে এক করে দেয়।


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

প্রথম Car :: String -> String -> Int -> Carধরণের ডেটা তৈরি করতে কেবল একটি ডেটা কনস্ট্রাক্টর ( ) ব্যবহার করা হয় Car। দ্বিতীয়টি Car :: a -> b -> c -> Car a b cটাইপের ডেটা তৈরি করতে কেবল একটি ডেটা কনস্ট্রাক্টর ( ) ব্যবহার করে Car a b c
নেস

উত্তর:


228

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

ডেটা কনস্ট্রাক্টর

জিনিসগুলিকে সহজ করার জন্য, আমরা একটি রঙের প্রতিনিধিত্ব করে এমন একটি উদাহরণ দিয়ে শুরু করতে পারি।

data Colour = Red | Green | Blue

এখানে আমাদের তিনটি ডেটা কনস্ট্রাক্টর রয়েছে। Colourএটি একটি প্রকার, এবং Greenএমন একটি নির্মাতা যা টাইপের মান ধারণ করে Colour। একইভাবে, Redএবং Blueউভয় কনস্ট্রাক্টর যা টাইপের মানগুলি তৈরি করে Colour। আমরা কল্পনা করতে পারি যদিও এটি স্পাইসিং করা যায়!

data Colour = RGB Int Int Int

আমাদের এখনও ঠিক টাইপ রয়েছে Colour, তবে RGBএটি কোনও মূল্য নয় - এটি একটি ফাংশন যা তিনটি ইনস নেয় এবং একটি মান ফেরত দেয় ! RGBটাইপ আছে

RGB :: Int -> Int -> Int -> Colour

RGBএটি একটি ডেটা কনস্ট্রাক্টর যা একটি ফাংশন যা তার মানগুলি আর্গুমেন্ট হিসাবে গ্রহণ করে এবং তারপরে নতুন মান তৈরি করতে সেগুলি ব্যবহার করে। আপনি যদি কোনও অবজেক্ট ভিত্তিক প্রোগ্রামিং করেন তবে আপনার এটি স্বীকৃতি দেওয়া উচিত। ওওপি-তে, কনস্ট্রাক্টররা আর্গুমেন্ট হিসাবে কিছু মানও নেয় এবং একটি নতুন মান ফেরত দেয়!

এই ক্ষেত্রে, আমরা RGBতিনটি মান প্রয়োগ করি, আমরা একটি রঙ মান পেতে!

Prelude> RGB 12 92 27
#0c5c1b

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

বিচ্ছেদ

আপনি যদি স্টোরের জন্য বাইনারি ট্রি তৈরি করতে চান তবে আপনি এমন Stringকিছু করার কথা ভাবতে পারেন

data SBTree = Leaf String
            | Branch String SBTree SBTree

আমরা এখানে যা দেখি তা হ'ল একটি প্রকার SBTreeযা দুটি ডেটা কনস্ট্রাক্টর ধারণ করে। অন্য কথায়, দুটি ফাংশন (যথা Leafএবং Branch) যা SBTreeধরণের মান তৈরি করবে । বাইনারি গাছগুলি কীভাবে কাজ করে সে সম্পর্কে আপনি যদি অবগত না হন তবে কেবল সেখানেই স্তব্ধ হন। বাইনারি গাছগুলি কীভাবে কাজ করে তা আপনাকে আসলে জানতে হবে না, কেবল এটি যে Stringকোনওভাবে সঞ্চয় করে ।

আমরা আরও দেখতে পেলাম যে উভয় ডেটা কনস্ট্রাক্টর একটি Stringযুক্তি নিয়েছে - এটি সেই স্ট্রিং যা তারা গাছের মধ্যে সংরক্ষণ করতে চলেছে।

কিন্ত! আমরা যদি সংরক্ষণ করতে সক্ষম হতে চাই তবে কী হবে Bool, আমাদের একটি নতুন বাইনারি ট্রি তৈরি করতে হবে। এটি এর মতো দেখতে পারে:

data BBTree = Leaf Bool
            | Branch Bool BBTree BBTree

কনস্ট্রাক্টর টাইপ করুন

উভয় SBTreeএবং BBTreeটাইপ নির্মাণকারী। তবে একটি উদ্ভট সমস্যা আছে। আপনি দেখতে পান যে তারা কতটা একই রকম? এটি এমন একটি চিহ্ন যা আপনি সত্যিই কোথাও একটি প্যারামিটার চান।

সুতরাং আমরা এটি করতে পারি:

data BTree a = Leaf a
             | Branch a (BTree a) (BTree a)

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

এখানে গুরুত্বপূর্ণ পার্থক্য বিবেচনা হয় কংক্রিট টাইপ (উদাহরণ অন্তর্ভুক্ত Int, [Char]এবং Maybe Bool) যা একটি টাইপ যে আপনার প্রোগ্রামে একটি মান নির্ধারিত করা যেতে পারে, এবং একটি টাইপ কন্সট্রাকটর ফাংশন যা আপনাকে একটি টাইপ ভোজন প্রয়োজন হতে পাবে একটি মান নির্ধারিত। একটি মান লিখুন "তালিকা" কখনো হতে পারে না কারণ এটি একটি "তালিকা করা প্রয়োজন কিছু "। একই আত্মায়, কোনও মান কখনই "বাইনারি ট্রি" আকারের হতে পারে না কারণ এটি "বাইনারি ট্রি কিছু সংরক্ষণের " হওয়া দরকার।

যদি আমরা ভিতরে প্রবেশ করি তবে বলুন, Boolযুক্তি হিসাবে BTreeএটি প্রকারটি প্রদান করে BTree Boolযা একটি বাইনারি গাছ যা সংরক্ষণ করে Bool। প্রকারের aসাথে চলকটির প্রতিটি ঘটনাকে প্রকারের সাথে প্রতিস্থাপন করুন Boolএবং আপনি কীভাবে এটি সত্য তা দেখতে পারেন।

আপনি যদি চান, আপনি BTreeএই ধরনের সঙ্গে একটি ফাংশন হিসাবে দেখতে পারেন

BTree :: * -> *

ধরণগুলি কিছুটা প্রকারের মতো হয় - এটি *একটি কংক্রিটের ধরণের ইঙ্গিত দেয়, তাই আমরা বলি BTreeএকটি কংক্রিটের থেকে কংক্রিটের ধরণে।

মোড়ক উম্মচন

এক মুহুর্তে এখানে ফিরে যান এবং সাদৃশ্যগুলি নোট করুন।

  • একটি ডেটা কন্সট্রাকটর একটি "ফাংশন" যে 0 বা আরো নেয় মান এবং আপনি ফিরে একটি নতুন মান দেয়।

  • একটি টাইপ কনস্ট্রাক্টর এমন একটি "ফাংশন" যা 0 বা ততোধিক প্রকার নেয় এবং আপনাকে নতুন টাইপ দেয়।

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

একটি কেস স্টাডি

এখানে বাড়ির প্রসারিত হিসাবে, আমরা Maybe aপ্রকারটি বিবেচনা করতে পারি । এর সংজ্ঞাটি হ'ল

data Maybe a = Nothing
             | Just a

এখানে, Maybeএকটি প্রকারের কনস্ট্রাক্টর যা একটি কংক্রিটের ধরণ দেয়। Justএকটি ডেটা কনস্ট্রাক্টর যা একটি মান দেয়। Nothingএকটি ডেটা কনস্ট্রাক্টর যাতে একটি মান রয়েছে। আমরা এর ধরণের দিকে নজর দিলে Justআমরা তা দেখতে পাই

Just :: a -> Maybe a

অন্য কথায়, Justটাইপের মান নেয় aএবং প্রকারের মান দেয় Maybe a। আমরা যদি ধরণের দিকে তাকাই তবে Maybeআমরা তা দেখতে পাই

Maybe :: * -> *

অন্য কথায়, Maybeএকটি কংক্রিট টাইপ নেয় এবং একটি কংক্রিট টাইপ প্রদান করে।

আরেকবার! একটি কংক্রিট টাইপ এবং একটি টাইপ কনস্ট্রাক্টর ফাংশনের মধ্যে পার্থক্য। আপনি যদি একটি Maybeএক্সিকিউট করার চেষ্টা করেন তবে আপনি এর একটি তালিকা তৈরি করতে পারবেন না

[] :: [Maybe]

আপনি একটি ত্রুটি পাবেন। তবে আপনি Maybe Intবা এর একটি তালিকা তৈরি করতে পারেন Maybe a। কারণ Maybeএটি একটি প্রকারের কনস্ট্রাক্টর ফাংশন, তবে একটি তালিকার জন্য একটি কংক্রিটের ধরণের মান থাকতে হবে। Maybe Intএবং Maybe aকংক্রিটের ধরণের (বা যদি আপনি চান, কনস্ট্রাক্টর ফাংশনগুলি টাইপ করার জন্য কলগুলি যা কংক্রিটের ধরণগুলি ফেরত দেয়))


2
আপনার প্রথম উদাহরণে, রেড গ্রিন এবং ব্লু উভয়ই এমন নির্মাতা যা কোনও যুক্তিই গ্রহণ করে না।
অলিবি

3
data Colour = Red | Green | Blue"আমাদের কোনও নির্মাণকারীর মোটেই নেই" দাবিটি সরল ভুল। টাইপ কনস্ট্রাক্টর এবং ডেটা কনস্ট্রাক্টরদের আর্গুমেন্ট নেওয়ার দরকার নেই, উদাহরণস্বরূপ haskell.org/haskellwiki/Constructor যা দেখায় যে data Tree a = Tip | Node a (Tree a) (Tree a)"এখানে দুটি ডাটা কনস্ট্রাক্টর, টিপ এবং নোড" রয়েছে।
ফ্রিরিচ রাবাব

1
আপনি সিএমসিডিআরগ্রাঙ্কাই ঠিক আছে! প্রকারভেদ হ'ল "প্রকারের ধরণ"। প্রকার এবং মানগুলির ধারণাগুলিতে যোগদানের একটি সাধারণ পদ্ধতিকে নির্ভর নির্ভর টাইপিং বলেইদ্রিস একটি হাস্কেল-অনুপ্রাণিত নির্ভর নির্ভর টাইপ করা ভাষা। ডান জিএইচসি এক্সটেনশনের সাহায্যে আপনি হাসকেলে নির্ভর টাইপিংয়ের কিছুটা কাছাকাছি যেতে পারেন। (কিছু লোক রসিকতা করছেন যে "" হেস্কেল গবেষণা নির্ভরশীল প্রকারগুলি না থাকলে আমরা নির্ভরশীল প্রকারের কতটা নিকটবর্তী হতে পারি তা নির্ধারণের বিষয়ে। ")
কেকিআর

1
@CMCDragonkai স্ট্যান্ডার্ড হাসকেলে খালি ডেটা ঘোষণা পাওয়া সম্ভব নয়। তবে একটি জিএইচসি এক্সটেনশন ( -XEmptyDataDecls) রয়েছে যা আপনাকে এটি করতে দেয়। যেহেতু, হিসাবে আপনি বলুন, যে ধরনের সঙ্গে কোনো মান নেই, একটি ফাংশন f :: Int -> Zউদাহরণস্বরূপ আসতে না পারে (কারণ তা ফিরে আসবে?) তারা কিন্তু জন্য উপযোগী হতে পারে যখন আপনি ধরনের চাই কিন্তু মান সত্যিই পরোয়া করি না
kqr

1
সত্যিই কি সম্ভব না? আমি কেবল জিএইচসিতে চেষ্টা করেছি, এবং এটি ত্রুটি ছাড়াই চালিয়েছে। আমাকে কোনও জিএইচসি এক্সটেনশন লোড করতে হয়নি, কেবল ভ্যানিলা জিএইচসি। আমি তখন লিখতে পারি :k Zএবং এটি আমাকে একটি তারা দিয়েছে।
সিএমসিডিগ্রাগনকাই

42

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

অন্যান্য ভাষায়, আপনি সাধারণত একটি "রেকর্ড", "স্ট্রাক্ট" বা অনুরূপ তৈরি করতে পারেন, এতে নামযুক্ত ক্ষেত্রগুলির একটি গুচ্ছ রয়েছে যা বিভিন্ন ধরণের ডেটা ধারণ করে। আপনি কখনও কখনও একটি "গণনা "ও তৈরি করতে পারেন, এতে স্থির সম্ভাব্য মানগুলির (যেমন, আপনার Red, Greenএবং Blue) একটি (ছোট) সেট থাকে ।

হাস্কেল এ আপনি একই সাথে উভয়কে একত্রিত করতে পারেন । অদ্ভুত, তবে সত্য!

কেন এটি "বীজগণিত" বলা হয়? ঠিক আছে, নার্ভগুলি "যোগফলগুলি" এবং "পণ্যের ধরণগুলি" সম্পর্কে কথা বলে। উদাহরণ স্বরূপ:

data Eg1 = One Int | Two String

একটি Eg1মান মূলত হয় একটি পূর্ণসংখ্যা বা একটি স্ট্রিং। সুতরাং সমস্ত সম্ভাব্য Eg1মানগুলির সেট হ'ল সম্ভাব্য পূর্ণসংখ্যার মান এবং সমস্ত সম্ভাব্য স্ট্রিং মানগুলির সেটগুলির "যোগফল"। সুতরাং, নার্ভগুলি Eg1একটি "যোগ টাইপ" হিসাবে উল্লেখ করে । অন্য দিকে:

data Eg2 = Pair Int String

প্রতিটি Eg2মান একটি পূর্ণসংখ্যা এবং একটি স্ট্রিং উভয় নিয়ে গঠিত । সুতরাং সমস্ত সম্ভাব্য Eg2মানগুলির সেট হ'ল সমস্ত পূর্ণসংখ্যার সেটের কার্টেসিয়ান পণ্য এবং সমস্ত স্ট্রিংয়ের সেট। দুটি সেট একসাথে "গুণিত", সুতরাং এটি একটি "পণ্যের ধরণ"।

Haskell, এর বীজগাণিতিক ধরনের হয় পণ্য ধরনের সমষ্টি ধরনের । আপনি পণ্যের ধরণ তৈরির জন্য একজন কনস্ট্রাক্টরকে একাধিক ক্ষেত্র দেন এবং আপনার যোগফল তৈরির জন্য একাধিক কনস্ট্রাক্টর থাকে (পণ্যগুলির)।

কেন এটি কার্যকর হতে পারে তার উদাহরণ হিসাবে, ধরুন আপনার কাছে এমন কিছু আছে যা XML বা JSON হিসাবে ডেটা আউটপুট করে এবং এটি একটি কনফিগারেশন রেকর্ড গ্রহণ করে - তবে স্পষ্টতই, এক্সএমএল এবং জেএসএনের জন্য কনফিগারেশন সেটিংস সম্পূর্ণ আলাদা। আপনি এখন পারে ভালো কিছু করতে:

data Config = XML_Config {...} | JSON_Config {...}

(সেখানে কিছু উপযুক্ত ক্ষেত্র রয়েছে, স্পষ্টতই)


4
মহান! উইকিপিডিয়াতে কেবল একটি জিনিস, "এগুলি ... প্রায় কোনও ভাষায় নির্মিত হতে পারে" । :) উদাহরণস্বরূপ সি / ++ এ, এটি unionএকটি ট্যাগ শৃঙ্খলা সহ। :)
নেস

5
হ্যাঁ, তবে প্রতিবারই আমি উল্লেখ করেছি union, লোকেরা আমার দিকে তাকিয়ে আছে "কে কখনও এই ব্যবহার করে ??" ;-)
গাণিতিক

1
আমি unionআমার সি ক্যারিয়ারে প্রচুর ব্যবহার দেখেছি । দয়া করে এটিকে অপ্রয়োজনীয় শব্দ করবেন না কারণ এটি ক্ষেত্রে নয়।
ট্রুথহোল্ডার

26

সবচেয়ে সহজ কেস দিয়ে শুরু করুন:

data Color = Blue | Green | Red

এই সংজ্ঞায়িত করে তা একটা "টাইপ কন্সট্রাকটর" Colorযা কোন যুক্তি লাগে - এবং তিন "তথ্য কনস্ট্রাকটর" আছে, Blue, Greenএবং Red। ডেটা কনস্ট্রাক্টরগুলির কোনওই আর্গুমেন্ট নেয় না। এই মানে ধরনের তিনটি আছে Color: Blue, Greenএবং Red

যখন আপনাকে কোনও ধরণের মান তৈরি করতে হবে তখন ডেটা কনস্ট্রাক্টর ব্যবহার করা হয়। ভালো লেগেছে:

myFavoriteColor :: Color
myFavoriteColor = Green

ডেটা কনস্ট্রাক্টর myFavoriteColorব্যবহার করে একটি মান তৈরি করে Green- এবং myFavoriteColorএটি টাইপ হবে Colorযেহেতু এটি ডেটা কনস্ট্রাক্টর দ্বারা উত্পাদিত মানের ধরণ।

একটি ধরণের কনস্ট্রাক্টর ব্যবহার করা হয় যখন আপনাকে কোনও ধরণের তৈরি করতে হবে । স্বাক্ষরগুলি লেখার সময় এটি সাধারণত:

isFavoriteColor :: Color -> Bool

এই ক্ষেত্রে, আপনি Colorটাইপ কনস্ট্রাক্টরকে কল করছেন (যা কোনও আর্গুমেন্ট নেয় না)।

এখনও আমার সাথে?

এখন, কল্পনা করুন যে আপনি কেবল লাল / সবুজ / নীল মান তৈরি করতে চেয়েছিলেন না তবে আপনি একটি "তীব্রতা" নির্দিষ্ট করতে চেয়েছিলেন। মত, 0 এবং 256 এর মধ্যে একটি মান You আপনি প্রতিটি ডেটা কনস্ট্রাক্টরের একটি যুক্তি যুক্ত করে এটি করতে পারেন, সুতরাং আপনার সাথে শেষ পর্যন্ত:

data Color = Blue Int | Green Int | Red Int

এখন, তিনটি ডেটা কনস্ট্রাক্টরের প্রত্যেকেই টাইপের একটি আর্গুমেন্ট নিয়ে থাকে Int। টাইপ কনস্ট্রাক্টর ( Color) এখনও কোনও আর্গুমেন্ট নেয় না। সুতরাং, আমার প্রিয় রঙটি একটি গাish় সবুজ, আমি লিখতে পারি

    myFavoriteColor :: Color
    myFavoriteColor = Green 50

এবং আবারও, এটি Greenডেটা কনস্ট্রাক্টরকে কল করে এবং আমি টাইপের একটি মান পাই Color

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

data Color a = Blue a | Green a | Red a

এখন, আমাদের টাইপ কনস্ট্রাক্টর একটি আর্গুমেন্ট নেয় (অন্য টাইপ যা আমরা কেবল ডাকি a!) এবং সমস্ত ডেটা কনস্ট্রাক্টর সেই ধরণের একটি যুক্তি (একটি মান!) নিবে a। সুতরাং আপনি থাকতে পারে

myFavoriteColor :: Color Bool
myFavoriteColor = Green False

অথবা

myFavoriteColor :: Color Int
myFavoriteColor = Green 50

লক্ষ্য করুন আমরা কীভাবে Colorটাইপ কনস্ট্রাক্টরকে "কার্যকর" টাইপ পেতে আর্গুমেন্ট (অন্য টাইপ) দিয়ে কল করি যা ডেটা কনস্ট্রাক্টররা ফেরত আসবে। এটি এমন এক ধরণের ধারণাকে স্পর্শ করে যা আপনি এক কাপ কফি বা দু'বার পড়তে চাইতে পারেন।

এখন আমরা নির্ধারণ করেছি যে ডেটা কনস্ট্রাক্টর এবং টাইপ কনস্ট্রাক্টর কী, এবং কীভাবে ডেটা কনস্ট্রাক্টররা অন্য মানগুলি আর্গুমেন্ট এবং টাইপ কনস্ট্রাক্টর হিসাবে আর্গুমেন্ট হিসাবে গ্রহণ করতে পারে। আছে HTH।


আমি নিশ্চিত ননালারি ডেটা কনস্ট্রাক্টরের ধারণাটি নিয়ে আমি বন্ধু friends আমি জানি এটি হাস্কেলের ধ্রুবকদের নিয়ে কথা বলার একটি সাধারণ উপায়, তবে এটি বেশ কয়েকবার ভুল প্রমাণিত হয়নি?
কেকআর

@ কেকিআর: একটি ডেটা কনস্ট্রাক্টর শুল্কযুক্ত হতে পারে তবে এটি আর কোনও কাজ নয়। একটি ফাংশন এমন একটি জিনিস যা একটি আর্গুমেন্ট গ্রহণ করে এবং একটি মান দেয়, অর্থাত্ ->স্বাক্ষরযুক্ত কিছু ।
ফ্রিরিচ রাবাবে

একাধিক প্রকারের জন্য একটি মান নির্দেশ করতে পারে? বা প্রতিটি মান কেবল 1 প্রকারের সাথে যুক্ত এবং এটিই?
সিএমসিডিগ্রাগনকাই

1
@jrg কিছু ওভারল্যাপ রয়েছে, তবে এটি বিশেষত টাইপ কনস্ট্রাক্টরের কারণে নয় তবে টাইপ ভেরিয়েবলের কারণে, যেমন aইন data Color a = Red aaএকটি স্বেচ্ছাসেবী প্রকারের জন্য একটি স্থানধারক। প্লেইন ফাংশনগুলিতে আপনার একই রকম থাকতে পারে, উদাহরণস্বরূপ টাইপের একটি ফাংশন (a, b) -> aদুটি মান (টাইপ aএবং এর b) এর একটি দ্বিগুণ লাগে এবং প্রথম মান দেয়। এটি একটি "জেনেরিক" ফাংশন যাতে এটি টিপল উপাদানগুলির প্রকারটি নির্দেশ করে না - এটি কেবল এটি নির্দিষ্ট করে যে ফাংশনটি প্রথম টুপল উপাদান হিসাবে একই ধরণের একটি মান দেয়।
ফ্রিরিচ রাবাব

1
+1 Now, our type constructor takes one argument (another type which we just call a!) and all of the data constructors will take one argument (a value!) of that type a.এটি খুব সহায়ক।
জোনাস

5

যেমনটি অন্যরা উল্লেখ করেছে, পলিমারফিজম এখানে এত ভয়ঙ্কর কার্যকর নয়। আসুন অন্য উদাহরণটি দেখুন যা আপনি সম্ভবত ইতিমধ্যে পরিচিত:

Maybe a = Just a | Nothing

এই ধরণের দুটি ডেটা কনস্ট্রাক্টর রয়েছে। Nothingকিছুটা বিরক্তিকর, এতে কোনও দরকারী ডেটা নেই। অন্যদিকে Justএকটি মান রয়েছে a- যা কিছু ধরণের aথাকতে পারে। আসুন একটি ফাংশন লিখুন যা এই ধরণের ব্যবহার করে, যেমন কোনও Intতালিকার শীর্ষস্থানীয় হওয়া , যদি কোনও থাকে (আমি আশা করি আপনি এটির সাথে একটি ত্রুটি নিক্ষেপের চেয়ে বেশি কার্যকর):

maybeHead :: [Int] -> Maybe Int
maybeHead [] = Nothing
maybeHead (x:_) = Just x

> maybeHead [1,2,3]    -- Just 1
> maybeHead []         -- None

সুতরাং এই ক্ষেত্রে aএকটি Int, কিন্তু এটি অন্য যে কোনও ধরণের জন্য পাশাপাশি কাজ করবে। আসলে আপনি আমাদের ফাংশনটি প্রতিটি ধরণের তালিকার জন্য তৈরি করতে পারেন (বাস্তবায়ন পরিবর্তন না করেও):

maybeHead :: [t] -> Maybe t
maybeHead [] = Nothing
maybeHead (x:_) = Just x

অন্যদিকে আপনি ফাংশন লিখতে পারেন যা কেবলমাত্র একটি নির্দিষ্ট ধরণের গ্রহণ করে Maybe, যেমন

doubleMaybe :: Maybe Int -> Maybe Int
doubleMaybe Just x = Just (2*x)
doubleMaybe Nothing= Nothing

এত দীর্ঘ গল্প সংক্ষিপ্ত, বহুবচন সহ আপনি নিজের ধরণের বিভিন্ন অন্যান্য ধরণের মানগুলির সাথে কাজ করার নমনীয়তা দিন।

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


আপনি কি অন্য ডেটা ঘোষণার ডেটা-প্রসঙ্গে টাইপ কনস্ট্রাক্টর ব্যবহার করতে পারেন? এরকম কিছু data Color = Blue ; data Bright = Color? আমি এটি জিসিআইতে চেষ্টা করে দেখেছি এবং দেখে মনে হয় যে উজ্জ্বল সংজ্ঞাতে রঙের ডেটা কনস্ট্রাক্টরের সাথে রঙের কোনও সম্পর্ক নেই। এখানে মাত্র 2 টি রঙিন কনস্ট্রাক্টর রয়েছে যার একটি হ'ল ডেটা এবং অন্যটি টাইপ।
সিএমসিডিগ্রাগনকাই

@CMCDragonkai আমি মনে করি না যে আপনি এটি করতে পারেন, এবং আপনি এটি দিয়ে কী অর্জন করতে চান তাও আমি নিশ্চিত নই। আপনি একটি বিদ্যমান ধরণটি "মোড়ানো" dataবা newtype(যেমন data Bright = Bright Color) ব্যবহার করে করতে পারেন, বা আপনি typeএকটি প্রতিশব্দ (উদাহরণ type Bright = Color) সংজ্ঞায়িত করতে ব্যবহার করতে পারেন ।
ল্যান্ডেই

5

দ্বিতীয়টিতে এর মধ্যে "পলিমারফিজম" ধারণাটি রয়েছে।

যে a b cকোনও ধরণের হতে পারে। উদাহরণস্বরূপ, aহতে পারে একটি [String], bহতে পারে [Int] এবং cহতে পারে[Char]

প্রথমটির ধরণ স্থিরকালে: সংস্থাটি একটি String, মডেল একটি Stringএবং বছর হয়Int

কার উদাহরণটি পলিমারফিজম ব্যবহারের তাত্পর্য না দেখায়। তবে কল্পনা করুন যে আপনার ডেটা তালিকার ধরণের। একটি তালিকা থাকতে পারেString, Char, Int ... সেই পরিস্থিতিতে আপনার নিজের ডেটা সংজ্ঞায়নের দ্বিতীয় উপায় প্রয়োজন will

তৃতীয় উপায় হিসাবে আমি এটি আগের ধরণের ফিট করতে হবে বলে মনে করি না। এটি হ্যাসকেলে ডেটা নির্ধারণের অন্য একটি উপায়।

এটি নিজেকে একজন শিক্ষানবিস হিসাবে আমার নম্র মতামত।

বিটিডব্লিউ: নিশ্চিত হয়ে নিন যে আপনি আপনার মস্তিষ্ককে ভালভাবে প্রশিক্ষণ দিয়েছেন এবং এতে স্বাচ্ছন্দ্য বোধ করছেন। এটি পরে মোনাদকে বোঝার মূল চাবিকাঠি।


1

এটা তোলে সম্বন্ধে ধরনের : প্রথম ক্ষেত্রে, আপনার সেট ধরনের String(কোম্পানী এবং মডেল জন্য) এবং Intবছরের জন্য। দ্বিতীয় ক্ষেত্রে, আপনার আরও জেনেরিক। a, bএবং cপ্রথম উদাহরণের মতো খুব একই ধরণের বা সম্পূর্ণ আলাদা কিছু হতে পারে । উদাহরণস্বরূপ, পূর্ণসংখ্যার পরিবর্তে বছরটিকে স্ট্রিং হিসাবে দেওয়া কার্যকর হতে পারে। এবং আপনি যদি চান, আপনি এমনকি আপনার Colorটাইপ ব্যবহার করতে পারেন ।

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