2011-12-12 9 views
7

में बेनामी कार्यों से सच्चे टेबल्स मैं एक दिए गए बूलियन अभिव्यक्ति के लिए एक सत्य तालिका उत्पन्न करने की कोशिश कर रहा हूं। मैं इसे एक नया डेटाटाइप BoolExpr बनाने के साथ कर सकता हूं, लेकिन मैं इसे एक अज्ञात फ़ंक्शन के साथ करना चाहता हूं। यह इस तरह से काम करने के लिए चाहिए था:हास्केल

> tTable (\x y -> not (x || y)) 
output: 
F F | T 
F T | F 
T F | F 
T T | F 

मेरे दृष्टिकोण:

tbl p = [(uncurry p) tuple | tuple <- allval] 
     where allval=[(x,y) | x <- [False,True], y <- [False,True]] 

यह काम करता है, लेकिन केवल 2 तर्क के लिए। मैं इसे किसी भी तर्क के लिए करना चाहता हूं। तो मैं सोचा मैं एक समारोह है कि एक सूची से तर्क लेता होगा:

argsFromList f []  = f 
argsFromList f (x:xs) = argsFromList (f x) xs 

यह काम नहीं करता:

Occurs check: cannot construct the infinite type: t = t1 -> t 
    Expected type: t -> [t1] -> t1 -> t 
    Inferred type: (t1 -> t) -> [t1] -> t1 -> t 
In the expression: argsFromList (f x) xs 

मुझे समझ नहीं आता कि समस्या क्या यहाँ है। यदि कोई मुझे सही दिशा में इंगित कर सकता है या एक लिंक पोस्ट कर सकता है तो मैं बहुत आभारी हूं।

+0

संभावित डुप्लिकेट [हैकेल में ऐसी फ़ंक्शन परिभाषा क्यों नहीं है?] (Http://stackoverflow.com/questions/6168880/why-is-such-a-function-definition-not-allowed-in- हैकसेल) –

+0

ध्यान दें कि आप लैम्ब्डा को '(\ [x, y] -> नहीं (x || y))' के रूप में परिभाषित कर सकते हैं, 'जो स्वचालित रूप से आपको "एक ही प्रकार के मनमाने ढंग से कई तर्कों के साथ कार्य करता है "। – leftaroundabout

उत्तर

4

समस्या यहाँ है कि आप पुनरावर्ती कदम के लिए एक अलग प्रकार के साथ रिकर्सिवली एक समारोह कॉल करने के लिए कोशिश कर रहे हैं। परिभाषा पर विचार करें:

argsFromList f []  = f 
argsFromList f (x:xs) = argsFromList (f x) xs 

के प्रकार अपने आप को अनुमान लगाने के लिए कोशिश करते हैं। हम तुरंत देख सकते हैं कि पहला तर्क f कम से कम एक तर्क के एक समारोह होना चाहिए, दूसरा तर्क (x:xs) एक सूची है, और सूची तत्वों f के पहले तर्क के रूप में एक ही प्रकार होना चाहिए। पहले मामले में तर्क f वापस कर दिया गया है, इसलिए अंतिम वापसी प्रकार पहले तर्क के समान होना चाहिए। इसलिए हम इस के साथ शुरू:

argsFromList :: (a -> ?) -> [a] -> (a -> ?) 

अज्ञात प्रकार ?, हम एक पुनरावर्ती कॉल के होते हैं जो दूसरे मामले, देख सकते हैं खोजने के लिए। तर्क xs एक ही सूची प्रकार है, और तर्क (f x) टाइप ? है। चूंकि इसे रिकर्सिव कॉल में पहले तर्क के रूप में उपयोग किया जा रहा है, जिसमें (a -> ?) टाइप किया गया है, अब हम निष्कर्ष निकाल सकते हैं कि ?(a -> ?) जैसा ही है, इसलिए (a -> (a -> ?)) जैसा ही है, जो (a -> (a -> (a -> ?))) जैसा ही है। ओह।

कि "अनंत प्रकार", निश्चित रूप से होगा।

आप कार्यों कि एक ही प्रकार के तर्कों के परिवर्तनशील का उपयोग के साथ ऐसा करना चाहते हैं, तो आप शायद कार्यों है कि व्यक्ति तर्क के बजाय मानों की सूची लेने का उपयोग करना चाहेंगे। अन्यथा, आपको या तो प्रत्येक संस्करण को व्यक्तिगत रूप से लिखना होगा या उन्नत भाषा सुविधाओं से जुड़े कुछ आर्केन चालों का उपयोग करना होगा, इनमें से कोई भी इस तरह के साधारण मामले में आकर्षक नहीं है।

+0

धन्यवाद! मैं इसे नए डेटाटाइप के साथ जाने और जाने दूँगा। – 1nterference

13

आप युक्तियों के स्वेच्छाचारी संख्या के साथ बूलियन कार्यों के लिए एक सच तालिका का निर्माण करना चाहते हैं, तो आप एक समारोह है कि कई प्रकार के लिए काम करना चाहिए बना रहे हैं, तो आप प्रकार वर्गों का उपयोग करना होगा:

{-# LANGUAGE FlexibleInstances #-} 

class TruthTable a where 
    truthTable :: a -> [([Bool], Bool)] 

instance TruthTable Bool where 
    truthTable b = [([], b)] 

instance TruthTable a => TruthTable (Bool -> a) where 
    truthTable f = [ (True : inps, out) | (inps, out) <- truthTable (f True)] ++ 
       [ (False : inps, out) | (inps, out) <- truthTable (f False)] 

उदाहरण के लिए:

*Main> mapM_ print $ truthTable (&&) 
([True,True],True) 
([True,False],False) 
([False,True],False) 
([False,False],False) 
2

क्या आप के लिए पूछ रहे हैं बिल्कुल तुच्छ नहीं है। हास्केल उन कार्यों से निपटने में आसान नहीं बनाता है जो तर्कों की चर संख्याओं के साथ कार्य लागू करते हैं।उदाहरण के लिए, zip functions from Data.List विभिन्न प्रकार के तर्कों के लिए अलग-अलग रूपों में आते हैं (zip, zip3, zip4, ...)। इसी तरह, Control.Monad में वहाँ liftM है, liftM2, liftM3 ...

असल में, सबसे सामान्य प्रकार आप बहस के एक अज्ञात संख्या के साथ एक समारोह के लिए प्रदान कर सकते हैं a -> b है; एक जगह सच्चाई समारोह Bool -> Bool है (एक = Bool, ख = Bool), एक दो जगह सच्चाई समारोह Bool -> (Bool -> Bool) है (एक = Bool, ख = Bool -> Bool), तीन जगह Bool -> (Bool -> (Bool -> Bool)) है (एक = Bool, ख = Bool -> (Bool -> Bool)) , और इसी तरह। लेकिन प्रारंभिक तीर के दाईं ओर क्या प्रकार है, यह जानने के लिए आप जिस समारोह में पारित हुए हैं, उस पर कोई आसान तरीका नहीं है।

काम के लिए किए जा सकने वाले एक प्रकार का समाधान प्रत्येक तर्क समारोह प्रकार के लिए सत्य-तालिका निर्माता फ़ंक्शन के अलग-अलग उदाहरणों को परिभाषित करने के लिए प्रकार कक्षाओं का उपयोग करना शामिल है। इस धागे में Sjoerd विस्चर का जवाब एक रिकर्सिव इंस्टेंस परिभाषा का उपयोग करके सभी फ़ंक्शन आकारों के लिए कर रहा है (रिकर्सिव TruthTable a => TruthTable (Bool -> a) घोषणा को नोटिस करें)। अन्य समाधान भी हो सकते हैं जिन्हें Applicative प्रकार वर्ग का उपयोग करके बनाया जा सकता है।