2010-07-29 15 views
6

read रूपहास्केल: पढ़ सकते हैं और टाइप हस्ताक्षर

read :: (Read a) => String -> a 

प्रस्तावना में परिभाषित किया गया है और जैसे के रूप में इस्तेमाल किया जा सकता read "1" :: Int

अब एक समारोह

readOne :: (Read a) => [String] -> (a, [String]) 
readOne (x:xs) = (read x,xs) 

साथ readOne ["1","foo"] परिणाम (अपेक्षित रूप से) त्रुटि

Ambiguous type variable 'a' in the constraint:
'Read a' arising from a use of 'readOne' at :1:0-18
Probable fix: add a type signature that fixes these type variable(s)

लेकिन readOne ["1","foo"] :: Int काम नहीं करता है में प्रयोग किया जाता है, जबकि

readOneInt :: [String] -> (Int, [String]) 
readOneInt = readOne 

काम करता है बस ठीक है:

> readOneInt ["1", "foo"] 
(1,["foo"]) 

तो: मैं कैसे readOneInt की तरह एक नया कार्य को परिभाषित करने के बिना readOne करने के लिए एक प्रकार हस्ताक्षर जोड़ सकते हैं?

उत्तर

9

readOne ["1","foo"] :: Int काम नहीं करता क्योंकि readOne संभवतः एक Int वापस नहीं कर सकता है, यह हमेशा एक टपल, जिसका दूसरा तत्व एक [String] है देता है। readOne ["1", "foo"] :: (Int, [String]) काम करेगा।

ध्यान दें कि आपको केवल उस प्रकार को निर्दिष्ट करने की आवश्यकता है यदि इसे अनुमानित नहीं किया जा सकता है। यदि आप संदर्भ में readOne के परिणाम का उपयोग करते हैं, जहां इसे Int होना आवश्यक है, तो आप readOne का उपयोग बिना एनोटेशन के कर सकते हैं। उदाहरण:

let inc (i, strs) = (i + 1, strs) in 
inc (readOne ["1", "foo"]) 
-- (2, ["foo"]) 
+0

आपको बहुत बहुत धन्यवाद! –

+2

सावधान रहें! अंत में उदाहरण केवल ghci में काम करेगा क्योंकि 1 का प्रकार 'इंटीजर' में डिफॉल्ट किया गया है। यदि आप अभिव्यक्ति के प्रकार के लिए ghci से पूछते हैं (': t' के माध्यम से), तो आपको' (Num a, Read a) => (ए, [स्ट्रिंग]) प्राप्त होता है, जिसका पहले जैसा ही समस्या है। 'asTypeOf' यहां सहायता कर सकता है, जैसा कि 'asTypeOf (readOne [" 1 "," foo "]) (0 :: डबल, [] :: [स्ट्रिंग])' - जिसे मैं आमतौर पर बैकटिक्स में टाइप टाइप के रूप में लिखूंगा लेकिन SO दोगुनी से बचने वाली बैकटीक्स पसंद नहीं है। – yatima2975

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