2012-03-05 18 views
10

में अनंत प्रकार को परिभाषित करना मैं परिभाषित करना चाहता हूं कि अनंत प्रकार की आवश्यकता क्या है।जानबूझकर हैशेल

आवश्यक: एक समारोह "खाने" है कि जिसके लिए यह रिटर्न 3

eat 3 = 3 
eat x = eat 

तो मूल रूप से की तरह एक मनमाना अभिव्यक्ति "खाने के (+) foldl (बस 5) 3" "3" के अलावा सभी यह तर्क खाती है 3 का मूल्यांकन करता है लेकिन यहां समस्या खाने का प्रकार है। वह क्या होना चाहिए?

करीबी एक चल रहा कोड के लिए मुझे मिल गया था:

newtype Rec = MakeRec (Int -> Rec) 

eat :: Int -> Rec 
eat x = MakeRec eat 


instance Show Rec where 
    show _ = "EAT" 

यह "6 खाने के लिए" ठीक काम करता है लेकिन नहीं "6 7 खाने के लिए" और अगर मैं डाल (खाने के 3 यह काम नहीं करता = 3) इसकी परिभाषा में।

मुझे यकीन नहीं है कि यह हास्केल में भी संभव है या नहीं। (यह दिखाने के लिए कोई तर्क क्या होगा कि यह संभव नहीं है?)

अद्यतन: जैसा कि नीचे दिए गए समाधान में बताया गया है, संकलन समय पर टाइप-सूचना की आवश्यकता है ताकि संकलक को पता चले कि "फ़ोल्डल 3 फोल्डल खाएं" अमान्य है या नहीं । तो, इस समस्या का सही समाधान संभव नहीं है।

उत्तर

21

यह संभव नहीं है। असीमित प्रकार (जो डेटा प्रकार नहीं हैं) को हास्केल में स्पष्ट रूप से वर्जित किया गया है, और कोड उत्पन्न करना आसान है, जिसके लिए उन्हें आवश्यकता होगी, और इस प्रकार एक त्रुटि उत्पन्न होती है (उदाहरण के लिए, let foo = (42, foo) in foo आज़माएं)।

आप निश्चित रूप से newtype और data के साथ बना सकते हैं, जैसा कि आपने किया था, लेकिन फिर आपको रचनाकारों के अंदर और बाहर मूल्यों को स्पष्ट रूप से लपेटना और खोलना होगा।

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

यानी, है typeclasses उपयोग करते हुए, अपने eat कार्य करने के लिए कुछ इसी तरह परिभाषित करने के लिए एक तरह से, लेकिन यह केवल नहीं रोक सकता जब आप इसे एक 3 दे: कि आप इसे दिया है एक 3 या नहीं कर सकते हैं केवल रनटाइम पर निर्धारित किया जाना चाहिए, और संकलन समय पर प्रकार का निर्धारण किया जाता है। हालांकि, यहां एक ओवरलोड मूल्य है कि दोनों एक Integer हो सकता है, और एक समारोह है कि सिर्फ अपनी तर्क अप खाती है:

class Eat a where 
    eat :: a 

instance Eat Integer where 
    eat = 3 

instance (Eat r) => Eat (a -> r) where 
    eat _ = eat 

पकड़ है कि आप जब आप इसका इस्तेमाल ठीक प्रकार निर्दिष्ट करने की आवश्यकता है:

*Main> eat 1 foldr() 

<interactive>:6:1: 
    Ambiguous type variable `t0' in the constraint: 
     (Eat t0) arising from a use of `eat' 
    Probable fix: add a type signature that fixes these type variable(s) 
    In the expression: eat 1 foldr() 
    In an equation for `it': it = eat 1 foldr() 
*Main> eat 1 foldr() :: Integer 
3 

ऐसा इसलिए है क्योंकि eat 1 foldr()Integer हो सकता है, लेकिन यह एक और कार्य भी हो सकता है, जैसा कि हमने eat 1 और eat 1 foldr का उपयोग उसी अभिव्यक्ति में कार्यों के रूप में किया था। दोबारा, हमें लचीली टाइपिंग मिलती है, लेकिन हमें उन प्रकारों को स्पष्ट रूप से निर्दिष्ट करना होगा जिन्हें हम बदले में चाहते हैं।

अधिक भार (42 किसी भी प्रकार Num का एक उदाहरण है कि हो सकता है) अतिभारित सांख्यिक शाब्दिक की तरह, typeclass सोचो।

+0

हैकेल में कोई अनंत प्रकार ठीक नहीं है। मैं जानना चाहता था कि यहां कोई काम है या नहीं, जो ** तकनीकी रूप से ** अनंत प्रकारों का उपयोग नहीं करता है लेकिन अभी भी – Karan

+0

काम करता है, जैसा कि आपने टिप्पणी पोस्ट की है, मैंने अपना उत्तर विस्तारित किया है; मुझे उम्मीद है कि यह उस अतिरिक्त प्रश्न का उत्तर देने में मदद करता है :) – ehird

+0

तो, हमेशा 3 रिटर्न खाते हैं, और किसी भी प्रकार (ए -> (बी-> .. इंटीजर) खाते हैं – Karan

संबंधित मुद्दे