नोट: यह उत्तर लेविट चर्चाओं पर हाल ही की टिप्पणियों पर आधारित है। Levity बहुरूपता के विषय में सब कुछ वर्तमान में केवल GHC 8.0 रिलीज़ उम्मीदवारों में लागू किया गया है और इस तरह के परिवर्तन के लिए ( उदाहरण के लिए # 11471 देखें )।
टीएल; डीआर : यह लिफ्ट और अनलिफ्टेड प्रकारों पर कार्यों को बहुरूपी बनाने का एक तरीका है, जो नियमित कार्यों के साथ संभव नहीं है। उदाहरण के लिए, निम्नलिखित कोड नियमित बहुरूपताओं के साथ चेक टाइप नहीं करता है, क्योंकि Int#प्रकार है #, लेकिन प्रकार में चर idप्रकार *:
{-# LANGUAGE MagicHash #-}
import GHC.Prim
example :: Int# -> Int#
example = id
Couldn't match kind ‘*’ with ‘#’
When matching types
a0 :: *
Int# :: #
Expected type: Int# -> Int#
Actual type: a0 -> a0
In the expression: id
ध्यान दें कि (->)अभी भी कुछ जादू का उपयोग करता है।
इससे पहले कि मैं इस सवाल का जवाब देना शुरू करते हैं, हमें एक कदम पीछे लेने के लिए और सबसे अक्सर इस्तेमाल किया कार्यों में से एक के लिए चलते हैं ($)।
($)प्रकार क्या है ? खैर, हैकेज और रिपोर्ट के अनुसार, यह है
($) :: (a -> b) -> a -> b
हालाँकि, यह 100% पूर्ण नहीं है। यह एक सुविधाजनक सा झूठ है। समस्या यह है कि बहुरूपी प्रकार (जैसे aऔर b) प्रकार के होते हैं *। हालांकि, (पुस्तकालय) डेवलपर्स ($)न केवल प्रकार के साथ *, बल्कि उन लोगों के लिए भी उपयोग करना चाहते थे #, जैसे
unwrapInt :: Int -> Int#
जबकि Intदयालु है *(यह नीचे हो सकता है), Int#दयालु है #(और बिल्कुल नीचे नहीं हो सकता)। फिर भी, निम्नलिखित कोड टाइप करें:
unwrapInt $ 42
यह काम नहीं करना चाहिए। वापसी प्रकार याद है ($)? यह बहुरूपी था, और बहुरूपी प्रकार दयालु है *, नहीं #! तो यह काम क्यों किया? सबसे पहले, यह एक बग था , और फिर यह एक हैक था ( ghc-dev मेलिंग सूची में रयान स्कॉट द्वारा एक मेल का अंश ):
तो ऐसा क्यों हो रहा है?
लंबा उत्तर यह है कि जीएचसी 8.0 से पहले, टाइप सिग्नेचर में ($) :: (a -> b) -> a -> b, bवास्तव में टाइप में नहीं *, बल्कि था OpenKind।
OpenKindएक भयावह हैक है जो दोनों (तरह *) को उठाता है और इसे हटाने के लिए अनलिमिटेड (प्रकार #) प्रकार देता है, यही कारण है कि (unwrapInt $ 42)
टाइपसेक।
तो ($)जीएचसी 8.0 में नया प्रकार क्या है ? आईटी इस
($) :: forall (w :: Levity) a (b :: TYPE w). (a -> b) -> a -> b
इसे समझने के लिए, हमें देखना होगा Levity:
data Levity = Lifted | Unlifted
अब, हम ($)निम्नलिखित में से किसी एक प्रकार के बारे में सोच सकते हैं, क्योंकि केवल दो विकल्प हैं w:
($) :: forall a (b :: TYPE Lifted). (a -> b) -> a -> b
($) :: forall a (b :: TYPE Unlifted). (a -> b) -> a -> b
TYPEएक जादुई स्थिरांक है, और यह प्रकार *और के #रूप में फिर से परिभाषित करता है
type * = TYPE Lifted
type # = TYPE Unlifted
प्रकार पर मात्रा का ठहराव भी काफी नया है और हास्केल में निर्भर प्रकारों के एकीकरण का हिस्सा है ।
नाम Levity polymorphism इस तथ्य से आता है कि अब आप उठा और अनपेक्षित दोनों प्रकारों पर बहुरूपी कार्य लिख सकते हैं, ऐसा कुछ जिसकी अनुमति पिछले बहुरूपता प्रतिबंधों के साथ संभव नहीं थी। साथ ही इससे OpenKindहैक से भी छुटकारा मिलता है । यह वास्तव में "बस" है इस बारे में, दोनों प्रकार के प्रकारों को संभालना।
वैसे, आप अपने प्रश्न के साथ अकेले नहीं हैं। यहां तक कि साइमन पेटन जोन्स ने कहा कि लेविटी विकी पेज की आवश्यकता है , और रिचर्ड ई (इस के वर्तमान कार्यान्वयनकर्ता) ने कहा कि विकी पेज को वर्तमान प्रक्रिया पर एक अपडेट की आवश्यकता है।
संदर्भ