Haskell Language
एप्लिकेशन टाइप करें
खोज…
परिचय
TypeApplications
एनोटेशन टाइप करने के लिए एक विकल्प है जब कंपाइलर किसी दिए गए एक्सप्रेशन के लिए TypeApplications
प्रकार का संघर्ष करता है।
उदाहरणों की यह श्रृंखला TypeApplications
एक्सटेंशन के उद्देश्य और इसका उपयोग करने के तरीके के बारे में TypeApplications
अपने स्रोत फ़ाइल के शीर्ष पर {-# LANGUAGE TypeApplications #-}
रखकर एक्सटेंशन को सक्षम करने के लिए मत भूलना।
टाइप एनोटेशन से बचना
हम अस्पष्टता से बचने के लिए प्रकार एनोटेशन का उपयोग करते हैं। टाइप एप्लिकेशन का उपयोग उसी उद्देश्य के लिए किया जा सकता है। उदाहरण के लिए
x :: Num a => a
x = 5
main :: IO ()
main = print x
इस कोड में अस्पष्टता त्रुटि है। हम जानते हैं कि a
Num
उदाहरण है, और इसे छापने के लिए हमें पता है कि इसे Show
आवश्यकता है। यह काम कर सकता है, तो a
था, उदाहरण के लिए, एक Int
, तो त्रुटि को ठीक करने हम एक प्रकार एनोटेशन जोड़ सकते हैं
main = print (x :: Int)
प्रकार अनुप्रयोगों का उपयोग कर एक और समाधान इस तरह दिखेगा
main = print @Int x
यह समझने के लिए कि हमें print
के प्रकार पर हस्ताक्षर करने का क्या मतलब है।
print :: Show a => a -> IO ()
फ़ंक्शन एक प्रकार का एक पैरामीटर लेता a
, लेकिन इसे देखने का एक और तरीका यह है कि यह वास्तव में दो पैरामीटर लेता है। पहला एक प्रकार पैरामीटर है, दूसरा एक मान है जिसका प्रकार पहला पैरामीटर है।
मूल्य मापदंडों और प्रकार के मापदंडों के बीच मुख्य अंतर यह है कि बाद वाले लोगों को अंतर्निहित रूप से कार्यों के लिए प्रदान किया जाता है जब हम उन्हें कॉल करते हैं। कौन उन्हें प्रदान करता है? प्रकार एल्गोरिथ्म एल्गोरिथ्म! TypeApplications
क्या करते हैं हम उन प्रकार के मापदंडों को स्पष्ट रूप से देते हैं। यह विशेष रूप से तब उपयोगी होता है जब प्रकार का अनुमान सही प्रकार निर्धारित नहीं कर सकता है।
तो उपरोक्त उदाहरण को तोड़ने के लिए
print :: Show a => a -> IO ()
print @Int :: Int -> IO ()
print @Int x :: IO ()
अन्य भाषाओं में एप्लिकेशन टाइप करें
यदि आप जावा, C # या C ++ जैसी भाषाओं से परिचित हैं और जेनरिक / टेम्प्लेट की अवधारणा है तो यह तुलना आपके लिए उपयोगी हो सकती है।
कहो कि हमारे पास C # में एक सामान्य कार्य है
public static T DoNothing<T>(T in) { return in; }
इस फ़ंक्शन को एक float
साथ कॉल करने के लिए हम DoNothing(5.0f)
कर सकते हैं या यदि हम स्पष्ट होना चाहते हैं तो हम DoNothing<float>(5.0f)
कह सकते हैं। कोण कोष्ठक के अंदर का हिस्सा प्रकार अनुप्रयोग है।
हास्केल में यह समान है, सिवाय इसके कि टाइप पैरामीटर न केवल कॉल साइटों पर बल्कि परिभाषा साइटों पर भी निहित हैं।
doNothing :: a -> a
doNothing x = x
इसे भी ScopedTypeVariables
, Rank2Types
या RankNTypes
एक्सटेंशन का उपयोग करके स्पष्ट किया जा सकता है।
doNothing :: forall a. a -> a
doNothing x = x
फिर कॉल साइट पर हम फिर से doNothing 5.0
या doNothing @Float 5.0
लिख सकते हैं
मापदंडों का क्रम
एक से अधिक होने के बाद, प्रकार के तर्कों के साथ समस्या स्पष्ट हो जाती है। वे किस क्रम में आते हैं?
const :: a -> b -> a
लेखन करता const @Int
मतलब a
के बराबर है Int
, या यह है b
? मामले में हम स्पष्ट रूप से एक प्रकार का उपयोग करते हुए पैरामीटर forall
जैसे कि const :: forall a b. a -> b -> a
तब आदेश जैसा लिखा है: a
, तब b
।
यदि हम नहीं करते हैं, तो चर का क्रम बाएं से दाएं है। उल्लेख किया जाने वाला पहला चर पहला प्रकार पैरामीटर है, दूसरा प्रकार दूसरा पैरामीटर है और इसी तरह।
क्या होगा यदि हम दूसरे प्रकार के चर को निर्दिष्ट करना चाहते हैं, लेकिन पहले को नहीं? हम इस तरह के पहले चर के लिए एक वाइल्डकार्ड का उपयोग कर सकते हैं
const @_ @Int
इस अभिव्यक्ति का प्रकार है
const @_ @Int :: a -> Int -> a
अस्पष्ट प्रकार के साथ बातचीत
मान लें कि आप एक प्रकार के वर्ग का परिचय दे रहे हैं जिनका आकार बाइट्स में है।
class SizeOf a where
sizeOf :: a -> Int
समस्या यह है कि आकार उस प्रकार के प्रत्येक मूल्य के लिए स्थिर होना चाहिए। हम वास्तव में sizeOf
फ़ंक्शन a
पर निर्भर नहीं करना चाहते हैं, लेकिन केवल इस पर टाइप करना है।
प्रकार अनुप्रयोगों के बिना, हमारे पास सबसे अच्छा समाधान था Proxy
प्रकार इस तरह परिभाषित किया गया था
data Proxy a = Proxy
इस प्रकार का उद्देश्य प्रकार की जानकारी ले जाना है, लेकिन कोई मूल्य जानकारी नहीं है। तब हमारा वर्ग ऐसा दिख सकता था
class SizeOf a where
sizeOf :: Proxy a -> Int
अब आप सोच रहे होंगे कि, पहले तर्क को पूरी तरह से क्यों नहीं छोड़ा जाए? हमारे कार्य का प्रकार तब सिर्फ sizeOf :: Int
या, अधिक सटीक होने के लिए क्योंकि यह एक वर्ग की एक विधि है, sizeOf :: SizeOf a => Int
या इससे भी अधिक स्पष्ट sizeOf :: forall a. SizeOf a => Int
।
समस्या प्रकार का अनुमान है। अगर मैं sizeOf
लिखता sizeOf
, तो, अनुमान एल्गोरिथ्म केवल जानता है कि मुझे एक Int
उम्मीद है। यह पता नहीं क्या लिखते हैं मैं के लिए स्थानापन्न करना चाहते है a
। इसके कारण, कंपाइलर द्वारा परिभाषा को अस्वीकार कर दिया जाता है जब तक कि आपके पास {-# LANGUAGE AllowAmbiguousTypes #-}
एक्सटेंशन सक्षम न हो। उस मामले में परिभाषा संकलित करती है, इसका उपयोग अस्पष्टता त्रुटि के बिना कहीं भी नहीं किया जा सकता है।
सौभाग्य से, प्रकार अनुप्रयोगों का परिचय दिन बचाता है! अब हम sizeOf @Int
लिख सकते हैं, स्पष्ट रूप से कह सकते हैं कि यह a
Int
। प्रकार अनुप्रयोग हमें एक प्रकार का पैरामीटर प्रदान करने की अनुमति देते हैं, भले ही यह फ़ंक्शन के वास्तविक मापदंडों में प्रकट न हो!