/ / मैं एक प्रकार के परिवार पर पैटर्न क्यों नहीं मिल सकता? - हैकेल, प्रकार

मैं एक प्रकार के परिवार पर पैटर्न क्यों नहीं मिल सकता? - हैकेल, प्रकार

निम्नलिखित कोड पर विचार करें:

{-# LANGUAGE TypeFamilies #-}

data Twothings a b = Twothings a b

type family Leftthing a where
Leftthing (Twothings a b) = Leftthing a
Leftthing a = a

leftthing :: a -> Leftthing a
leftthing (Twothings a b) = leftthing a
leftthing b = b

यह निम्नलिखित त्रुटि के साथ संकलित नहीं करता है:

Couldn"t match expected type ‘a’
with actual type ‘Twothings a0 t0’
‘a’ is a rigid type variable bound by
the type signature for:
leftthing :: forall a. a -> Leftthing a

यह लाइन के बारे में शिकायत करता है leftthing (Twothings a b) = leftthing a। अगर मैं सही ढंग से समझता हूं, तो यह टाइप वैरिएबल को एकीकृत नहीं कर सकता है a कन्स्ट्रक्टर के प्रकार के साथ प्रकार हस्ताक्षर में Twothings। ठीक है, यह समझ में आता है। परन्तु फिर, मैं प्रकार हस्ताक्षर में प्रकार परिवारों के साथ एक समारोह को कैसे परिभाषित कर सकता हूं?

उत्तर:

उत्तर № 1 के लिए 11

जब आप घोषित करते हैं

leftthing :: a -> Leftthing a

आप कह रहे हैं कि फोन करने वाले का leftthing क्या चुनने के लिए हो जाता है a है।

जब आप लिखते हैं

leftthing (Twothings a b) = leftthing a

तुम हो अपने ऊपर भरोसा रखनेवाला कि उन्होंने एक चुना है Twothings टाइप करें, और जैसा कि आवश्यक नहीं है, आपका प्रोग्राम अस्वीकार कर दिया गया है।

आपने सोचा होगा कि आप थे परीक्षण कर रहा है या नहीं उन्होंने एक चुना था Twothings टाइप करें, लेकिन नहीं! रन टाइम से पहले जानकारी मिटा दी जाती है, इसलिए ऐसा परीक्षण करने का कोई तरीका नहीं है।

आप कर सकते हैं आवश्यक रन टाइम जानकारी बहाल करने का प्रयास करें। सबसे पहले मुझे आपके बीच असंगतता को ठीक करने दें Leftthing तथा leftthing

type family Leftthing a where
Leftthing (Twothings a b) = Leftthing{-you forgot the recursion!-} a
Leftthing a = a

अब हम गवाहों के जीएडीटी को परिभाषित कर सकते हैं Twothingसाय।

data IsItTwothings :: * -> * where
YesItIs   :: IsItTwothings a -> IsItTwothings (Twothings a b)
NoItIsn"t :: Leftthing a ~ a => IsItTwothings a
-- ^^^^^^^^^^^^^^^ this constraint will hold for any type
-- which is *definitely not* a Twothings type

और फिर हम गवाह को एक तर्क के रूप में पारित कर सकते हैं:

leftthing :: IsItTwothings a -> a -> Leftthing a
leftthing (YesItIs r) (Twothings a b) = leftthing r a
leftthing NoItIsn"t   b               = b

असल में, गवाह बाएं-नेस्टेड की संख्या का असीमित एन्कोडिंग है Twothingsअपने प्रकार की जड़ पर es। यह पर्याप्त जानकारी है कि रन टाइम पर निर्धारित करने के लिए सही मात्रा में अनपॅकिंग करें।

> leftthing (YesItIs (YesItIs NoItIsn"t)) (Twothings (Twothings True 11) (Twothings "strange" [42]))
True

संक्षेप में, आप पैटर्न द्वारा एक प्रकार का पता नहीं लगा सकते हैंएक मूल्य पर मिलान। इसके बजाय, आपको पैटर्न मिलान करने के प्रकार को जानने की आवश्यकता है (क्योंकि प्रकार मेमोरी लेआउट निर्धारित करता है, और कोई रन टाइम प्रकार टैग नहीं होते हैं)। आप सीधे प्रकारों पर पैटर्न मिलान नहीं कर सकते हैं (क्योंकि वे "मिलान करने के लिए अभी नहीं हैं)। आप डेटा प्रकारों का निर्माण कर सकते हैं जो प्रकार की संरचना के रन टाइम सबूत के रूप में कार्य करते हैं और इसके बजाय उन पर मेल खाते हैं।

शायद, एक दिन, यदि आप इसे टाइप करते हैं तो आपका प्रोग्राम काम करेगा

leftthing :: pi a. a -> Leftthing a

कहा पे pi आश्रित क्वांटिफायर है, जो दर्शाता है कि छुपा प्रकार तर्क मिटाया नहीं गया है, बल्कि रन टाइम पर पास किया गया है और मिलान किया गया है। वह दिन अभी तक नहीं आया है, लेकिन मुझे लगता है कि यह होगा।