2013-04-04 12 views
6

बस एक त्वरित वैचारिक सवाल है, मैं वर्तमान में हास्केल को बेहतर तरीके से सीखने और समझने की कोशिश कर रहा हूं।फ़ंक्शंस के लिए कोई शो उदाहरण क्यों नहीं है?

मुझे पता है कि शो फ़ंक्शन का उपयोग तारों को स्ट्रिंग में बदलने के लिए किया जाता है, लेकिन शो के साथ फ़ंक्शन प्रकार का उपयोग क्यों नहीं किया जा सकता है?

Prelude> (\x -> x*3) 

<interactive>:7:1: 
    No instance for (Show (a0 -> a0)) 
     arising from a use of `print' 
    Possible fix: add an instance declaration for (Show (a0 -> a0)) 
    In a stmt of an interactive GHCi command: print it 
Prelude> 
+0

उस समारोह के लिए आप 'स्ट्रिंग' का उत्पादन करने की अपेक्षा करेंगे? –

उत्तर

10

ऐसा नहीं है कि वे नहीं कर सकते हैं, लेकिन आमतौर पर इसका कोई अच्छा कारण नहीं है।

लेकिन अगर आप चाहें, तो आप निश्चित रूप से कर सकते हैं:

Prelude> :{ 
Prelude| instance Show (a -> b) where 
Prelude| show _ = "A function." 
Prelude| :} 
Prelude> print (\x -> x + 7) 
A function. 
Prelude> print (\a b c -> a + b + c) 
A function. 

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

+2

वास्तव में एक 'शो' उदाहरण बनाया गया है। यह एक सामान्य प्रश्न है - [यहां] (http://stackoverflow.com/questions/15015698/derive-eq-and-show-for-type-alias-in- हैकेल/15015731 # 15015731) और [यहां] (उदाहरण के लिए http://stackoverflow.com/questions/10551210/instance-show-for-function/10551513#10551513)। –

3

show समारोह है कि कार्यों कि Show typeclass के सदस्य हैं पर परिभाषित किया जाता है (यदि आप नहीं जानते कि एक typeclass है, यह एक OOP इंटरफ़ेस की तरह थोड़े है)।

डिफ़ॉल्ट रूप से, फ़ंक्शन टाइपक्लास के सदस्य नहीं हैं, इसलिए हम उन्हें प्रिंट नहीं कर सकते हैं।

हम इसे

instance Show (a -> b) where 
    show f = "Unicorns!!" 

साथ typeclass के एक सदस्य बना सकता है, लेकिन यहाँ हम पता है क्यों यह डिफ़ॉल्ट रूप से लागू नहीं है। कार्यों का एक सरल, स्पष्ट प्रतिनिधित्व नहीं है और हैकेल अनुमान लगाना नहीं चाहता है, और इस प्रकार कोई उदाहरण नहीं है।

एकमात्र "अनुमत" उदाहरण एक ऐसा होगा जो वास्तव में कार्य को प्रिंट करता है, लेकिन इसके लिए वास्तविक भाषा परिवर्तन की आवश्यकता होगी, यानी यह संकलक में कड़ी मेहनत की जाएगी, जो कि कुछ मामलों के लिए उपयुक्त नहीं है यह उपयोगी हो सकता है।

इसके अलावा अधिक यह एक nontrivial संकलक परिवर्तन है, हास्केल संकलित किया गया है जो f = g और

f =    g 

की तरह कुछ के बीच मतभेदों को पूरी तरह से इस पर खो रहे हैं मतलब है। लेकिन आप निश्चित रूप से अपने समारोह के प्रतिनिधित्व में चाहते हैं। इस वजह से, आपको कार्यक्रम के माध्यम से इस स्ट्रिंग के चारों ओर घूमना होगा। यह निश्चित रूप से नहीं है कि आप बाइनरी में क्या चाहते हैं।

यदि आप वाकई इसे यूनिकोरन्स प्रिंट करना चाहते हैं !! हालांकि, नि: शुल्क महसूस करें।

+0

जेनक्स! मुझे लगता है कि यह ध्यान देने योग्य है कि क्यों (बड़े) संकलक में परिवर्तन की आवश्यकता होगी: हास्केल संकलित कोड के कई विवरण स्ट्रिप्स। – amindfv

+0

जीईसी के साथ निष्पक्षता में, मध्यवर्ती भाषाओं में उचित मात्रा में जानकारी बरकरार रहती है, हालांकि असली फ़ंक्शन टेक्स्ट, यानी व्हाइटस्पेस जैसी चीजें, पार्सिंग के बाद गायब हो जाती हैं और हमेशा के लिए चली जाती हैं। पीएस "यूनिकॉर्न !!" "एक समारोह" से कहीं अधिक जानकारीपूर्ण है। : पी – jozefg

+4

एक तर्क भी बनाया जा सकता है कि अर्थात्, \ x -> 3 * x' और '\ x -> x * 3' एक ही कार्य हैं (कम से कम 'Int' पर), तो आपके पास या तो होगा उन दोनों के बीच अंतर करने के लिए 'आईओ' मोनैड में दोनों का प्रतिनिधित्व करने या काम करने के लिए मनमाने ढंग से एक स्ट्रिंग चुनने के लिए। – hammar

7

एक आंशिक समाधान है जो डेटा का उपयोग कर सभी कार्यों के लिए केवल एक निश्चित स्ट्रिंग से परे चला जाता है। टाइप करने योग्य।

{-# LANGUAGE ScopedTypeVariables #-} 

import Data.Typeable 

instance (Typeable a, Typeable b) => Show (a->b) where 
    show _ = show $ typeOf (undefined :: a -> b) 
GHCi

> let test :: Int->Int; test x = x + x 
> test 
Int -> Int 

में

दुर्भाग्य से एक प्रकार हस्ताक्षर के बिना प्रकार यह डिफ़ॉल्ट के लिए जाना जाएगा।

> let test x = x + x 
> test 
Integer -> Integer 

यह समाधान कई समारोह arities पर काम करता है क्योंकि a -> b -> ca -> (b -> c) के रूप में ही है जो आप के रूप में अच्छी a -> d जहां d = b -> c के रूप में लिख सकते हैं है।

> let m10 a b c d e f g h i j = a * b * c * d * e * f * g * h* i * j 
> m10 
Integer -> Integer -> Integer -> Integer -> Integer -> Integer -> Integer 
     -> Integer -> Integer -> Integer -> Integer 

इस विधि हालांकि काम नहीं करता है जब यह अज्ञात है अगर समारोह के मापदंडों typeable वर्ग तथापि है इसलिए जब map (+1) काम करेंगे map नहीं होगा।

> map (+1) 
[Integer] -> [Integer] 
> map 

<interactive>:233:1: 
... 

Data.Data के आंतरिक भागों और एक प्रयोग या दो पर एक नज़र में करने के बाद ऐसा लगता है जैसे कि यह एक छोटे से अधिक सामान्यीकृत कवर अधिक कार्यों होने के लिए पुनर्संशोधित जा सकता है।

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