হাস্কেলের অস্তিত্বের প্রকারের বিষয়ে স্পষ্টতা


10

আমি হাসকেলে অস্তিত্বের ধরণগুলি বোঝার চেষ্টা করছি এবং একটি পিডিএফ এসেছি http://www.ii.uni.wroc.pl/~dabi/courses/ZPF15/rlasocha/prezentacja.pdf

আমার এখন পর্যন্ত আমার নীচের উপলব্ধিগুলি সংশোধন করুন।

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

আমার সন্দেহ

  • উপরের পিডিএফের 20 পৃষ্ঠায় নীচের কোডের জন্য উল্লেখ করা হয়েছে যে কোনও ফাংশনের পক্ষে নির্দিষ্ট বাফার দাবি করা অসম্ভব। এটা এমন কেন? আমি যখন কোনও ফাংশন খসড়া করছি তখন আমি ঠিক জানি যে আমি কী ধরনের বাফারের ইভেন্টটি ব্যবহার করব তা আমি জানি না যে আমি কী ডেটা রেখেছি। থাকার ক্ষেত্রে কী আছে :: Worker MemoryBuffer Intযদি তারা সত্যিকার অর্থে বাফারের উপর বিমূর্ত করতে চায় তবে তাদের একটি যোগফল থাকতে পারে data Buffer = MemoryBuffer | NetBuffer | RandomBufferএবং এর মতো ধরণের থাকতে পারে:: Worker Buffer Int
data Worker x = forall b. Buffer b => Worker {buffer :: b, input :: x}
data MemoryBuffer = MemoryBuffer

memoryWorker = Worker MemoryBuffer (1 :: Int)
memoryWorker :: Worker Int
  • যেহেতু হাস্কেল সি-র মতো একটি সম্পূর্ণ প্রকারের ক্ষয়ের ভাষা তাই রানটাইমে কীভাবে কল করতে হয় তা এটি কীভাবে জানবে। এটি কি এমন কিছু যা আমরা কিছু তথ্য বজায় রাখি এবং একটি বিশাল ভি-টেবিলের কার্যাদিতে পাস করি এবং রানটাইমগুলিতে এটি ভি-টেবিল থেকে বেরিয়ে আসে? এটি যদি তাই হয় তবে তথ্যটি কী ধরণের এটি সঞ্চয় করবে?

উত্তর:


8

GADT এর অন্তর্ভুক্ত forall সরবরাহ করে অস্তিত্বমূলক প্রকারগুলি ব্যবহার করে কোডের স্পষ্ট এবং আরও ভাল সিনট্যাক্স সরবরাহ করে

আমি মনে করি যে GADT বাক্য গঠন আরও ভাল যে সাধারণ চুক্তি আছে। আমি এটি বলব না যে এটি জিএডিডিগুলি অন্তর্নিহিত ফোরায়েল সরবরাহ করে, বরং এটি ExistentialQuantificationএক্সটেনশান সহ সক্ষম হওয়া মূল সিনট্যাক্সটি সম্ভবত বিভ্রান্ত / বিভ্রান্তিকর। এই বাক্য গঠনটি অবশ্যই দেখায়:

data SomeType = forall a. SomeType a

বা একটি বাধা সহ:

data SomeShowableType = forall a. Show a => SomeShowableType a

এবং আমি মনে করি যে sensক্যমত্যটি হ'ল forallএখানে কীওয়ার্ড ব্যবহারের ফলে প্রকারটি সম্পূর্ণ ভিন্ন ধরণের সাথে সহজেই বিভ্রান্ত হতে পারে:

data AnyType = AnyType (forall a. a)    -- need RankNTypes extension

আরও ভাল সিনট্যাক্স একটি পৃথক existsকীওয়ার্ড ব্যবহার করতে পারে , তাই আপনি লিখতে চাই:

data SomeType = SomeType (exists a. a)   -- not valid GHC syntax

অন্তর্নিহিত বা স্পষ্টরূপে ব্যবহৃত GADT বাক্য গঠনটি এই ধরণেরগুলির forallমধ্যে আরও অভিন্ন এবং এটি বোঝা আরও সহজ বলে মনে হয়। এমনকি একটি স্পষ্টতা সহ forall, নিম্নলিখিত সংজ্ঞাটি এই ধারণাটি জুড়ে যায় যে আপনি যে কোনও ধরণের মান নিতে পারেন aএবং এটি মনোমরফিকের ভিতরে রাখতে পারেন SomeType':

data SomeType' where
    SomeType' :: forall a. (a -> SomeType')   -- parentheses optional

এবং এই ধরণের এবং এর মধ্যে পার্থক্যটি দেখতে এবং বোঝা সহজ:

data AnyType' where
    AnyType' :: (forall a. a) -> AnyType'

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

আমরা প্রকারগুলি গোপন করতে চাইলে সেগুলি ব্যবহার করি (উদাহরণস্বরূপ: ভিন্ন ভিন্ন তালিকাগুলির জন্য) বা কমপাইল টাইমের প্রকারগুলি কী তা আমরা সত্যই জানি না।

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

data SomeShowableType' where
    SomeShowableType' :: forall a. (Show a) => a -> SomeShowableType'

আপনাকে "বাক্স" এর ভিতরে উঁকি দিতে এবং ধরণের শ্রেণিবদ্ধ সুবিধাগুলি উপলভ্য করার জন্য প্যাটার্ন ম্যাচের অনুমতি দেয়:

showIt :: SomeShowableType' -> String
showIt (SomeShowableType' x) = show x

মনে রাখবেন যে এটি কেবল Typeableবা না কোনও ধরণের শ্রেণির জন্য কাজ করে Data

স্লাইড ডেকের 20 পৃষ্ঠাগুলি সম্পর্কে আপনার বিভ্রান্তির বিষয়ে, লেখক বলছেন যে কোনও ফাংশনের পক্ষে এটি একটি অসম্ভব যা একটি নির্দিষ্ট উদাহরণের Workerদাবিতে অস্তিত্ব গ্রহণWorker করে Buffer। আপনি Workerএকটি নির্দিষ্ট ধরণের ব্যবহার করে তৈরি করতে একটি ফাংশন লিখতে পারেন Buffer, যেমন MemoryBuffer:

class Buffer b where
  output :: String -> b -> IO ()
data Worker x = forall b. Buffer b => Worker {buffer :: b, input :: x}
data MemoryBuffer = MemoryBuffer
instance Buffer MemoryBuffer

memoryWorker = Worker MemoryBuffer (1 :: Int)
memoryWorker :: Worker Int

তবে আপনি যদি এমন কোনও ফাংশন লিখেন যা একটি Workerযুক্তি হিসাবে গ্রহণ করে , তবে এটি কেবলমাত্র সাধারণ Bufferধরণের শ্রেণীর সুবিধা (যেমন, ফাংশন output) ব্যবহার করতে পারে:

doWork :: Worker Int -> IO ()
doWork (Worker b x) = output (show x) b

bপ্যাটার্ন ম্যাচিংয়ের মাধ্যমে এমনকি এটি একটি বিশেষ ধরণের বাফার হওয়ার দাবি করার চেষ্টা করতে পারে না :

doWorkBroken :: Worker Int -> IO ()
doWorkBroken (Worker b x) = case b of
  MemoryBuffer -> error "try this"       -- type error
  _            -> error "try that"

পরিশেষে, অস্তিত্বমূলক প্রকার সম্পর্কিত রানটাইম তথ্য জড়িত টাইপক্লাসগুলির জন্য অন্তর্নিহিত "অভিধান" আর্গুমেন্টের মাধ্যমে উপলব্ধ করা হয়। Workerটাইপ উপরে বাফার এবং ইনপুট জন্য ক্ষেত্র হচ্ছে addtion মধ্যে, এছাড়াও একটি অদৃশ্য অন্তর্নিহিত ক্ষেত্র পয়েন্ট যে হয়েছে Bufferঅভিধান (কিছুটা ভি-টেবিল মত, যদিও এটা কমই বিশাল, এটা ঠিক উপযুক্ত একটি পয়েন্টার রয়েছে যেমন outputফাংশন)।

অভ্যন্তরীণভাবে, টাইপ শ্রেণিটি Bufferফাংশন ক্ষেত্রগুলির সাথে ডেটা টাইপ হিসাবে উপস্থাপিত হয় এবং উদাহরণগুলি এই ধরণের "অভিধান" থাকে:

data Buffer' b = Buffer' { output' :: String -> b -> IO () }

dBuffer_MemoryBuffer :: Buffer' MemoryBuffer
dBuffer_MemoryBuffer = Buffer' { output' = undefined }

অস্তিত্বের ধরণের এই অভিধানের জন্য একটি গোপন ক্ষেত্র রয়েছে:

data Worker' x = forall b. Worker' { dBuffer :: Buffer' b, buffer' :: b, input' :: x }

এবং doWorkঅস্তিত্বের Worker'মানগুলিতে পরিচালনা করে এমন একটি ফাংশন হিসাবে প্রয়োগ করা হয়:

doWork' :: Worker' Int -> IO ()
doWork' (Worker' dBuf b x) = output' dBuf (show x) b

শুধুমাত্র একটি ফাংশন সহ একটি ধরণের শ্রেণীর জন্য অভিধানটি আসলে নতুন টাইপকে অনুকূলিত করে তোলে, সুতরাং উদাহরণস্বরূপ, অস্তিত্বের ধরণটিতে Workerএকটি গোপন ক্ষেত্র অন্তর্ভুক্ত থাকে outputযা বাফারের জন্য ফাংশনটির জন্য একটি ফাংশন পয়েন্টার ধারণ করে এবং এটি কেবলমাত্র রানটাইম তথ্য প্রয়োজন দ্বারা doWork


অস্তিত্বগুলি কি ডেটা ঘোষণার জন্য 1 র‌্যাঙ্কের মতো? কোন ওওপি ভাষার মতো হাস্কেলের ভার্চুয়াল ফাংশনগুলি মোকাবেলার উপায় অস্তিত্বের?
পবন কুমার

1
আমার সম্ভবত AnyTypeর‌্যাঙ্ক -2 টাইপ না বলা উচিত ছিল ; এটি কেবল বিভ্রান্তিকর, এবং আমি এটি মুছে ফেলেছি। কনস্ট্রাক্টর AnyTypeর‌্যাঙ্ক -2 ফাংশনের মতো কাজ করে এবং কনস্ট্রাক্টর SomeTypeএকটি র‌্যাঙ্ক -1 ফাংশন (কেবলমাত্র বেশিরভাগ অ- অস্তিত্বমূলক ধরণের মতো) কাজ করে তবে এটি খুব সহায়ক সহায়ক বৈশিষ্ট্য নয়। যদি কিছু হয় তবে এই ধরণেরগুলি আকর্ষণীয় করে তোলে তা হ'ল এগুলি 0 (যেমন কোনও ধরণের ভেরিয়েবলের উপরে পরিমাণযুক্ত নয় এবং তাই একরকম) যদিও তারা "পরিমাণযুক্ত" প্রকারভেদ করে।
কেএ বুহর

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

4

উপরের পিডিএফের 20 পৃষ্ঠায় নীচের কোডের জন্য উল্লেখ করা হয়েছে যে কোনও ফাংশনের পক্ষে নির্দিষ্ট বাফার দাবি করা অসম্ভব। এটা এমন কেন?

কারণ Worker, সংজ্ঞায়িত হিসাবে, কেবল একটি যুক্তি লাগে, "ইনপুট" ক্ষেত্রের ধরণ (ধরণের ভেরিয়েবল x)। যেমন Worker Intএকটি প্রকার। bপরিবর্তে ভেরিয়েবল টাইপটি প্যারামিটার নয় Worker, তবে এটি "স্থানীয় ভেরিয়েবল" এর এক ধরণের, তাই কথা বলতে। এটি যেমন হিসাবে পাস করা যায় না Worker Int String- এটি কোনও ধরণের ত্রুটি ঘটায়।

আমরা পরিবর্তে সংজ্ঞায়িত হলে:

data Worker x b = Worker {buffer :: b, input :: x}

তাহলে Worker Int Stringকাজ করবে, তবে টাইপটি আর অস্তিত্বহীন নয় - আমাদের এখন সর্বদা বাফার টাইপটিও পাস করতে হবে।

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

এটি মোটামুটি সঠিক is সংক্ষেপে বলতে Workerগেলে , প্রতিবার আপনি কন্সট্রাক্টর প্রয়োগ করার সময় জিএইচসি bতার যুক্তিগুলি থেকে প্রকারটি নির্ধারণ করে Workerএবং তারপরে একটি উদাহরণ অনুসন্ধান করে Buffer b। যদি এটি পাওয়া যায় তবে জিএইচসি অবজেক্টের উদাহরণে একটি অতিরিক্ত পয়েন্টার অন্তর্ভুক্ত করে। এর সর্বাধিক আকারে, ভার্চুয়াল ফাংশন উপস্থিত থাকলে ওওপি-র প্রতিটি বস্তুর সাথে যুক্ত করা "পয়েন্টার টু ভিটিবেল" থেকে এটি খুব বেশি আলাদা নয়।

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

প্রতিটি ক্ষেত্রে জিএইচসি ঠিক কী কাজ করে তা অনুমান করা শক্ত: এটি এক টন অপ্টিমাইজেশনের উপর নির্ভর করে যা সম্ভবত ট্রিগার হতে পারে বা না পারে।

কী চলছে তা সম্পর্কে আরও জানতে আপনি "ডিকশনারি ভিত্তিক" টাইপ শ্রেণীর প্রয়োগের জন্য গুগল করার চেষ্টা করতে পারেন। আপনি জিএইচসিকে অভ্যন্তরীণ অনুকূলিত কোরটি মুদ্রণ -ddump-simplকরতে এবং ডিকশনারিগুলি নির্মান, সঞ্চিত এবং চারপাশে পাশ করা পর্যবেক্ষণ করতে বলতে পারেন। আমাকে আপনাকে সতর্ক করতে হবে: কোর বরং নিম্ন স্তরের এবং প্রথমে পড়া শক্ত হতে পারে।

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