2012-02-27 22 views
7

मैं एक ट्यूपल को क्रेट करना चाहता हूं, जिसमें एक तीर और तीर है जो तीर का वर्णन करती है।टस्कल्स के अंदर हास्केल तीर

funTimes10 = (*10) 
describe10 = "times 10" 

tuple10 :: (Num b) => ((b -> b), String) 
tuple10 = (,) funTimes10 describe10 

मैं fst साथ समारोह का उपयोग कर सकते हैं, और snd साथ मैं समारोह का वर्णन स्ट्रिंग प्राप्त: अगर मैं कार्यों (तीर के बजाय), निम्न कार्य करता उम्मीद की तरह साथ ऐसा करते हैं।

हालांकि, अगर मैं निम्नलिखित में ऐरो से समारोह का आदान-प्रदान, जैसे:

aTuple10 :: (Arrow a, Num b) => (a b b, String) 
aTuple10 = (,) (arr funTimes10) describe10 
  • fst अभी भी काम करता है और मेरी तीर दिखाए, लेकिन
  • मैं के साथ किसी भी वर्णन स्ट्रिंग नहीं मिलता है snd

मैं केवल इस त्रुटि-संदेश मिला:

Ambiguous type variable `a0' in the constraint: 
    (Arrow a0) arising from a use of `aTuple10' 
Probable fix: add a type signature that fixes these type variable(s) 
In the first argument of `snd', namely `aTuple10' 
In the expression: (snd aTuple10) 
In an equation for `it': it = (snd aTuple10) 

मैं इस त्रुटि क्यों मिलता है, और मुझे क्या करना चाहिए, यह से बचने के लिए? snd के प्रकार पर

उत्तर

9

आइए नज़र:

snd :: (foo, x) -> x 

(मैं स्पष्टता के लिए प्रकार चर का नाम बदला) किस तरह के कथन कहता है कि प्रकार foo और x के साथ एक टपल के लिए, वापसी के बारे में कुछ x टाइप करें। यहां जानना महत्वपूर्ण है कि मूल्य प्रणाली उर्फ। हास्केल में रनटाइम आलसी है, हास्केल की टाइप सिस्टम सख्त है, जिसका अर्थ यह है कि foo और x दोनों प्रकार snd से पहले ज्ञात होना चाहिए।

पहला मामला है, जब तुम सिर्फ एक Num b => (b -> b, String) है, snd बुला b अस्पष्ट छोड़ देंगे, क्योंकि आप अपने ठोस प्रकार कहीं भी उल्लेख नहीं है, और यह वापसी प्रकार से नहीं लगाया जा सकता क्योंकि foo ~ b जो अलग है x से। दूसरे शब्दों में: क्योंकि (b, b)कोई संख्या प्रकार का एक टुपल हो सकता है, और प्रकार चेकर यह पता नहीं लगा सकता कि यह कौन सा है, यह संदिग्ध है। यहां की चाल यह है कि हमारे पास हास्केल के डिफ़ॉल्ट नियमों को लात मार दिया जाएगा, जो बताता है कि यदि एक संख्यात्मक प्रकार संदिग्ध है, तो इसे Integer पर डिफ़ॉल्ट होना चाहिए। अगर आपने -Wall के साथ चेतावनियां चालू की हैं, तो यह कहा होगा कि यह हो रहा है। तो, हमारा प्रकार (Integer -> Integer, String) और snd कहा जा सकता है।

दूसरे मामले में, हालांकि, हम अभी भी दोषी नियमों के माध्यम से b का अनुमान लगा लेते हैं, लेकिन कोई डिफ़ॉल्ट a के लिए Arrow है, इसलिए हम अटक रहे हैं! जारी रखने के लिए आपको स्पष्ट रूप से निर्दिष्ट करना होगा कि आप कौन सा तीर चाहते हैं! आप पहली बार कहीं और aTuple10 के एक मूल्य का उपयोग करके ऐसा या तो कर सकते हैं:

let bla = aTuple10 -- We do this because `aTuple10` can have type variables, but `bla` cannot (by default) 
fst bla (23 :: Int) -- This fixes the type of `bla`, so that `a ~ (->)` and `b ~ Int` 
print $ snd bla  -- So the arrow isn't ambiguous here 

...या यदि आप बस प्रकार है कि आप चाहते हैं निर्दिष्ट कर सकते हैं:

print $ snd (aTuple10 :: (Int -> Int, String)) 

पुनश्च आप अस्पष्ट संख्या के डिफ़ॉल्ट प्रकार को बदलना चाहते हैं, default keyword आप मदद कर सकते हैं।

+0

यह बिल्कुल है;) thx – frosch03

+1

कितना परेशान है। एक उम्मीद करेगा कि टाइप सिस्टम यह निष्कर्ष निकालने में सक्षम होगा कि 'snd aTuple10' में' स्ट्रिंग' टाइप है; क्या इसे कार्यान्वयन में एक बग माना जा सकता है? निश्चित रूप से हास्केल 2010 इस तरह के व्यवहार को निर्दिष्ट नहीं करता है। कोई तर्क दे सकता है कि यदि कार्यान्वयन नहीं जानता कि पहली चीज़ किस प्रकार है, तो यह नहीं पता कि दूसरी बात मेमोरी में कहां है, लेकिन चूंकि हम यहां बॉक्स किए गए ट्यूपल्स से निपट रहे हैं, इसलिए हमेशा दो पॉइंटर्स होना चाहिए, और इसलिए पहला तत्व आसानी से पहले के प्रकार के बावजूद locatable है। –

+2

'क्लास बूलिश' जैसे एक समारोह जहां बूल :: ए -> बूल; foo :: बूलिश ए => (ए, बी) -> बी; foo (ए, बी) = यदि एक बुलबुला है तो बी और अपरिभाषित 'कल्पनाशील है, इसलिए फ़ंक्शन का परिणाम अस्पष्ट पैरामीटर पर निर्भर हो सकता है। उस स्थिति में 'snd' के लिए विशेष आवरण अजीब होगा। – dflemstr

-1

मैं इस संकलन करने की कोशिश की:

import Control.Arrow 

funTimes10 = (*10) 
describe10 = "times 10" 

tuple10 :: (Num b) => ((b -> b), String) 
tuple10 = (,) funTimes10 describe10 

aTuple10 :: (Arrow a, Num b) => (a b b, String) 
aTuple10 = (,) (arr funTimes10) describe10 

लेकिन मैं इस मिल:

Could not deduce (b ~ Integer) 
from the context (Arrow a, Num b) 
    bound by the type signature for 
      aTuple10 :: (Arrow a, Num b) => (a b b, String) 
    at D:\dev\haskell\arr_tuple.hs:10:1-42 
    `b' is a rigid type variable bound by 
     the type signature for 
     aTuple10 :: (Arrow a, Num b) => (a b b, String) 
     at D:\dev\haskell\arr_tuple.hs:10:1 
Expected type: b -> b 
    Actual type: Integer -> Integer 
In the first argument of `arr', namely `funTimes10' 
In the first argument of `(,)', namely `(arr funTimes10)' 

तो, मेरा अनुमान है कि आप जो तीर उदाहरण आप उपयोग करना चाहते तय की जरूरत है। अर्थात। आपको एनोटेशन के साथ ठोस प्रकार arr funTimes निर्दिष्ट करने की आवश्यकता हो सकती है।

+0

यहां की त्रुटि हाथ में समस्या से पूरी तरह से असंबंधित है। ऐसा प्रतीत होता है क्योंकि आप 'funTimes10' के लिए एक प्रकार का हस्ताक्षर भूल गए हैं। [मोनोमोर्फिज्म प्रतिबंध] देखें (http://www.haskell.org/haskellwiki/Monomorphism_restriction)। – dflemstr

+0

@dflemstr क्या मेरा उत्तर मूल प्रश्न के साथ एक समस्या दिखाता है? ** मैं ** एक प्रकार के हस्ताक्षर को नहीं भूल गया, यह मूल पोस्ट में नहीं था। हालांकि मैंने अंतर्निहित समस्या का वर्णन नहीं किया (क्योंकि मैंने इसे नहीं देखा), मुझे नहीं लगता कि यह मेरे जवाब को कम करने योग्य है। – Andre

+1

मुझे लगता है कि ओपी ने अपने कार्यों की परिभाषा की प्रतिलिपि बनाई है ताकि यह प्रदर्शित किया जा सके कि वह किस प्रकार के मूल्यों का उपयोग कर रहा है। उसके पास एक पॉलीमोर्फिक 'मजेदार टाइम्स 10' है, या वह एक अलग त्रुटि प्राप्त कर लेता। – dflemstr