मैं हास्केल reflection पैकेज के साथ खेल रहा था, और मैं एक प्रकार की त्रुटि में भाग गया जो मैं पूरी तरह समझ नहीं पा रहा हूं।प्रतिबिंबित इस रहस्यमय हास्केल प्रकार त्रुटि का कारण क्या है?
{-# LANGUAGE TypeApplications #-}
reifyGood :: (forall s. Reifies s a => Proxy a) ->()
reifyGood p = reify undefined (\(_ :: Proxy t) -> p @t `seq`())
दिलचस्प बात यह है, तथापि, यह थोड़ा अलग कार्यक्रम करता नहीं typecheck:
reifyBad :: (forall s. Reifies s s => Proxy s) ->()
reifyBad p = reify undefined (\(_ :: Proxy t) -> p @t `seq`())
• Could not deduce (Reifies s s) arising from a use of ‘p’
from the context: Reifies s a0
bound by a type expected by the context:
Reifies s a0 => Proxy s ->()
• In the first argument of ‘seq’, namely ‘p @t’
In the expression: p @t `seq`()
In the second argument of ‘reify’, namely
‘(\ (_ :: Proxy t) -> p @t `seq`())’
प्रथम, मैं निम्नलिखित समारोह है, जो खुशी से typechecks लिखने का प्रयास किया अभिव्यक्ति समान हैं, लेकिन प्रकार हस्ताक्षर के बीच अंतर ध्यान दें:
reifyGood :: (forall s. Reifies s a => Proxy a) ->()
reifyBad :: (forall s. Reifies s s => Proxy s) ->()
मुझे यह उत्सुक लगता है। पहली नज़र में, यह अमान्य है क्योंकि, दूसरे उदाहरण में, skolem s
इसके दायरे से बच जाएगा। बहरहाल, यह वास्तव में सच-त्रुटि संदेश कभी नहीं है यह थोड़ा अलग कार्यक्रम के साथ Skolem भागने का उल्लेख है, इसके विपरीत में:
reifyBad' :: (forall s. Reifies s s => Proxy s) ->()
reifyBad' p = reify undefined (\(_ :: Proxy t) -> p @t) `seq`()
• Couldn't match expected type ‘t0’ with actual type ‘Proxy s’
because type variable ‘s’ would escape its scope
This (rigid, skolem) type variable is bound by
a type expected by the context:
Reifies s a0 => Proxy s -> t0
• In the expression: p @t
In the second argument of ‘reify’, namely
‘(\ (_ :: Proxy t) -> p @t)’
In the first argument of ‘seq’, namely
‘reify undefined (\ (_ :: Proxy t) -> p @t)’
तो शायद कुछ और यहाँ खेलने पर है।
reify
के प्रकार की जांच करना, यह एक छोटे स्पष्ट हो जाता है कि कुछ गड़बड़ है:
reify :: forall a r. a -> (forall s. Reifies s a => Proxy s -> r) -> r
a
और s
का स्कोप, स्पष्ट रूप से अलग हैं तो यह है कि GHC उन्हें अनुमति नहीं होगी समझ बनाने के लिए लगता है एकजुट। हालांकि, ऐसा लगता है कि Reifies
पर कार्यात्मक निर्भरता द्वारा पेश की गई स्थानीय समानता बाधा के बारे में कुछ ऐसा लगता है जो किसी प्रकार का अजीब व्यवहार करता है। दिलचस्प बात यह है कार्यों typechecks की यह जोड़ी:
foo :: forall a r. Proxy a -> (forall s. (s ~ a) => Proxy s -> r) -> r
foo _ f = f Proxy
bar :: (forall a. Proxy a) ->()
bar p = let p' = p in foo p' (\(_ :: Proxy s) -> (p' :: Proxy s) `seq`())
... लेकिन foo
के प्रकार के हस्ताक्षर में समानता बाधा को दूर करने के लिए उन्हें typecheck करने में विफल है, एक Skolem भागने त्रुटि उत्पादन: इस बिंदु पर
• Couldn't match type ‘a0’ with ‘s’
because type variable ‘s’ would escape its scope
This (rigid, skolem) type variable is bound by
a type expected by the context:
Proxy s ->()
Expected type: Proxy s
Actual type: Proxy a0
• In the first argument of ‘seq’, namely ‘(p' :: Proxy s)’
In the expression: (p' :: Proxy s) `seq`()
In the second argument of ‘foo’, namely
‘(\ (_ :: Proxy s) -> (p' :: Proxy s) `seq`())’
, मैं परेशान हूँ। मेरे पास एक जोड़े (अत्यधिक संबंधित) प्रश्न हैं।
reifyBad
पहली जगह में typecheck को क्यों असफल रहा है?अधिक विशेष रूप से, यह अनुपलब्ध उदाहरण त्रुटि क्यों उत्पन्न करता है?
इसके अलावा, इस व्यवहार की उम्मीद है और अच्छी तरह से परिभाषित, या यह महज typechecker कि इस विशेष परिणाम उपज होता है का एक अजीब किनारे मामला है?