2013-08-07 4 views
7

में टाइप `स्ट्रिंग -> स्ट्रिंग` प्रकार के प्रकार 'ए -> बी' प्रकार के कार्यों को ट्रांसफॉर्म करना मेरा इरादा सरल है। मैं a -> b के String -> String में कार्यों को लपेटना चाहता हूं (ताकि विषम कार्यों का एक समूह सूची में रखा जा सके)। तो मैं लिखना:हास्केल

wrap :: (Read a, Show b) => (a -> b) -> (String -> String) 
wrap f = \s -> show $ f (read s :: a) 

हालांकि, ghc शिकायतें:

Could not deduce (Read a1) arising from a use of `read' 
from the context (Read a, Show b) 
    bound by the type signature for 
      wrap :: (Read a, Show b) => (a -> b) -> String -> String 

मुझे पता है क्यों कोड की मेरी टुकड़ा काम नहीं करेगा चाहते हैं और हैक्स किस तरह मेरा लक्ष्य प्राप्त करने की आवश्यकता है?

धन्यवाद।

+3

सूची में विषम कार्यों का एक गुच्छा रखना अच्छा हैकेल नहीं है, और स्ट्रिंग रूपांतरण में उन्हें अपनाने से निश्चित रूप से खराब हैकेल है। आप एक बड़ी समझ में क्या करने की कोशिश कर रहे हैं? – NovaDenizen

+0

यह एक गलती है। ऐसा मत करो। आप हास्केल की शक्तिशाली प्रकार प्रणाली को फेंक रहे हैं, और इसके साथ चलने वाली सभी महान संकलन-समय की जांच कर रहे हैं। एक मैकेनिक जो आपको अपनी कार बताता है वह ठीक है और फिर यह फ्रीवे पर टूट जाता है, यह मैकेनिक के रूप में उतना ही उपयोग नहीं करता है जो आपको कुछ 50 डॉलर तय करने के लिए कहता है (अब, जब यह गेराज में है) जो आपको तोड़ने का कारण बन रहा है नीचे (बाद में, इसके बाद और अधिक नुकसान हुआ, वहां एक कॉल-आउट शुल्क है और जिस व्यक्ति को फिक्सिंग करने वाला व्यक्ति उसके पास उस हिस्से का हिस्सा नहीं है)। स्टेटिक टाइपिंग अच्छी मैकेनिक है, डायनामिक टाइपिंग वह है जो कहती है कि यह ठीक है। – AndrewC

+0

@ नोवाडेनज़ेन मैं निश्चित रूप से स्थिर टाइपिंग में हूं। हाल ही में मैं एक साधारण सर्वर लिख रहा हूं। 'ए -> आईओ बी 'एक कार्यान्वित सेवा के लिए खड़ा है। एक घटक '[(स्ट्रिंग, ए -> आईओ बी)] '' 'मैप स्ट्रिंग (ए -> आईओ बी) में कनवर्ट करना है। लेकिन टाइप सिस्टम उस अनुमति नहीं देता है। मेरे पास टाइप सुरक्षा को लागू करने के लिए मेरे दिमाग में प्रकारों की अधिक जटिल डिज़ाइन है (ताकि क्लाइंट को 'ए'> आईओ बी 'की सेवा में' ए 'प्रकार के इनपुट को खिलाना पड़े, अन्यथा पूरा प्रोग्राम टाइप नहीं करेगा चेक)। लेकिन पकड़ यह है कि सर्वर हास्केल में लिखे गए ग्राहकों की सेवा नहीं कर सकता है। तो मेरा तंत्र उस मामले में काम नहीं करता है। – tfboy

उत्तर

13

आपका कोड काम नहीं करेगा क्योंकि हास्केल नहीं फिर से उपयोग या गुंजाइश प्रकार चर करता है, awrap :: (Read a, Show b) => (a -> b) -> (String -> String)read s :: a में से एक से पूरी तरह अलग a है (और वे दोनों सार्वभौमिक रूप से प्रमाणित हैं)। यह त्रुटि संदेश में a1 का स्रोत है; GHC अल्फा परिवर्तित

wrap :: (Read a, Show b) => (a -> b) -> (String -> String) 
wrap f = \s -> show $ f (read s :: a1) 

हालांकि, f तर्क प्रकार wrap अंदर तय हो गई है करने के लिए कार्यक्रम है, तो बस को हटाने प्रकार एनोटेशन ठीक काम करता है है। आपका समारोह

wrap :: (Read a, Show b) => (a -> b) -> (String -> String) 
wrap f = \s -> show $ f (read s) 
    -- Or wrap f = show . f . read 

हो जाता है और आप इसे उपयोग कर सकते हैं: इसका मतलब है

ghci> map ($ "42") [wrap (+ (7 :: Integer)), wrap (* (2.0 :: Double))] 
["49","84.0"] 

ध्यान दें कि यह read s एक प्रकार आप नीचे नहीं लिख सकता है। हास्केल 2010 (या 98) में, इसके आसपास जाने का एकमात्र तरीका asTypeOf :: a -> a -> a जैसे फ़ंक्शन का उपयोग करना है; asTypeOf सिर्फ const है, लेकिन इसके प्रकार के हस्ताक्षर के लिए धन्यवाद, यह इसके पहले, लौटे, तर्क को दूसरे प्रकार के समान होने के लिए बाध्य करता है। फिर, ज़ाहिर है, आपको a प्रकार के चर को अपनाना होगा। निम्नलिखित है कि के लिए काम करेगा:

wrap :: (Read a, Show b) => (a -> b) -> (String -> String) 
wrap f = \s -> show $ f (read s `asTypeOf` fInput) 
    where fInput = undefined 
     fOutput = f fInput -- I still can't give this a type signature 

GHC में, इस से बचने के लिए, आप the ScopedTypeVariables extension चालू कर सकते हैं; इसके साथ, यदि आप forall के साथ अपने सभी प्रकार के चर को स्पष्ट रूप से अर्हता प्राप्त करते हैं, तो उन्हें मूल्य-स्तर के नामों की तरह ही स्कॉप्ड किया जाएगा। फिर आपका कोड

{-# LANGUAGE ScopedTypeVariables #-} 
wrap :: forall a b. (Read a, Show b) => (a -> b) -> (String -> String) 
wrap f = \s -> show $ f (read s :: a) 

याद रखें, आपको इस सरल उदाहरण के लिए किसी भी प्रकार की टिप्पणियों की आवश्यकता नहीं है।

10

read s के प्रकार स्पष्ट रूप से निर्दिष्ट करने के लिए, आप ScopedTypeVariables की तरह कुछ की आवश्यकता होगी:

{-# LANGUAGE ScopedTypeVariables #-} 
... 
wrap :: forall a b. (Read a, Show b) => (a -> b) -> (String -> String) 
wrap f = \s -> show $ f (read s :: a) 

अन्यथा बाद से समारोह के अंदर :: a टिप्पणी का प्रकार हस्ताक्षर में a से एक अलग प्रकार के लिए संदर्भित करता परोक्ष (यह मतलब :: forall a. a)। लेकिन ध्यान दें कि आप भी सिर्फ पूरी तरह प्रकार एनोटेशन ड्रॉप कर सकते हैं:

wrap :: (Read a, Show b) => (a -> b) -> (String -> String) 
wrap f = \s -> show $ f (read s) 

के बाद से read s के प्रकार निष्कर्ष निकाला जा सकता। यही कारण है कि यह भी आप

करने के लिए शरीर को आसान बनाने की सुविधा देता है
wrap f = show . f . read