मुझे वाक्य-रचना का कोई प्रकाशित संस्करण दिखाई नहीं देता है, जिसके हस्ताक्षर sugarSym
उन सटीक प्रकार नामों का उपयोग करते हैं, इसलिए मैं अंतिम संस्करण 8cfd02 ^ पर विकास शाखा का उपयोग करूंगा , जो अभी भी उन नामों का उपयोग करता है।
तो, जीएचसी fi
आपके प्रकार के हस्ताक्षर के बारे में शिकायत क्यों करता है लेकिन किसके लिए नहीं sugarSym
? आपके द्वारा जोड़ा गया दस्तावेज़ यह बताता है कि एक प्रकार अस्पष्ट है यदि यह बाधा के दाईं ओर दिखाई नहीं देता है, जब तक कि बाधा अन्य गैर-अस्पष्ट प्रकारों से अन्यथा अस्पष्ट प्रकार का अनुमान लगाने के लिए कार्यात्मक निर्भरता का उपयोग नहीं कर रही है। तो आइए दोनों कार्यों के संदर्भों की तुलना करें और कार्यात्मक निर्भरताओं की तलाश करें।
class ApplySym sig f sym | sig sym -> f, f -> sig sym
class SyntacticN f internal | f -> internal
sugarSym :: ( sub :<: AST sup
, ApplySym sig fi sup
, SyntacticN f fi
)
=> sub sig -> f
share :: ( Let :<: sup
, sup ~ Domain b
, sup ~ Domain a
, Syntactic a
, Syntactic b
, Syntactic (a -> b)
, SyntacticN (a -> (a -> b) -> b) fi
)
=> a -> (a -> b) -> b
इसलिए sugarSym
, गैर-अस्पष्ट प्रकार हैं sub
, sig
और f
उन लोगों से, जिन्हें हम संदर्भ में उपयोग किए जाने वाले अन्य सभी प्रकारों को अलग करने के लिए कार्यात्मक निर्भरता का पालन करने में सक्षम होना चाहिए, sup
और fi
। और वास्तव में, f -> internal
में कार्यात्मक निर्भरता SyntacticN
हमारे उपयोग करता है f
हमारे को स्पष्ट करने के लिए fi
, और उसके बाद f -> sig sym
में कार्यात्मक निर्भरता ApplySym
का उपयोग करता है हमारे नव disambiguated fi
को स्पष्ट करने के लिए sup
(और sig
है, जो पहले से ही गैर अस्पष्ट था)। तो यह बताता है कि विस्तार की sugarSym
आवश्यकता क्यों नहीं है AllowAmbiguousTypes
।
आइए अब नजर डालते हैं sugar
। पहली बात जो मैंने नोटिस की है कि कंपाइलर अस्पष्ट प्रकार के बारे में शिकायत नहीं कर रहा है, बल्कि उदाहरणों को ओवरलैप करने के बारे में है:
Overlapping instances for SyntacticN b fi
arising from the ambiguity check for ‘share’
Matching givens (or their superclasses):
(SyntacticN (a -> (a -> b) -> b) fi1)
Matching instances:
instance [overlap ok] (Syntactic f, Domain f ~ sym,
fi ~ AST sym (Full (Internal f))) =>
SyntacticN f fi
-- Defined in ‘Data.Syntactic.Sugar’
instance [overlap ok] (Syntactic a, Domain a ~ sym,
ia ~ Internal a, SyntacticN f fi) =>
SyntacticN (a -> f) (AST sym (Full ia) -> fi)
-- Defined in ‘Data.Syntactic.Sugar’
(The choice depends on the instantiation of ‘b, fi’)
To defer the ambiguity check to use sites, enable AllowAmbiguousTypes
इसलिए अगर मैं यह सही पढ़ रहा हूं, तो ऐसा नहीं है कि जीएचसी को लगता है कि आपके प्रकार अस्पष्ट हैं, बल्कि यह भी है कि यह जांचते समय कि आपके प्रकार अस्पष्ट हैं, जीएचसी को एक अलग, अलग समस्या का सामना करना पड़ा। यह तब आपको बता रहा है कि यदि आपने GHC को अस्पष्टता जांच नहीं करने के लिए कहा है, तो उसे उस अलग समस्या का सामना नहीं करना पड़ेगा। यह बताता है कि AllowAmbiguousTypes को सक्षम करना आपके कोड को संकलित करने की अनुमति क्यों देता है।
हालांकि, अतिव्यापी उदाहरणों के साथ समस्या बनी हुई है। जीएचसी ( SyntacticN f fi
और SyntacticN (a -> f) ...
) द्वारा सूचीबद्ध दो उदाहरण एक दूसरे के साथ ओवरलैप करते हैं। अजीब तरह से, ऐसा लगता है कि इनमें से पहले को किसी अन्य उदाहरण के साथ ओवरलैप करना चाहिए, जो संदिग्ध है। और क्या करता है[overlap ok]
मतलब है?
मुझे संदेह है कि Syntactic OverlappingInstances के साथ संकलित है। और कोड को देखते हुए , वास्तव में यह करता है।
थोड़ा प्रयोग करने पर, ऐसा लगता है कि जीएचसी अतिव्यापी उदाहरणों के साथ ठीक है जब यह स्पष्ट है कि एक दूसरे की तुलना में अधिक सामान्य है:
{-# LANGUAGE FlexibleInstances, OverlappingInstances #-}
class Foo a where
whichOne :: a -> String
instance Foo a where
whichOne _ = "a"
instance Foo [a] where
whichOne _ = "[a]"
-- |
-- >>> main
-- [a]
main :: IO ()
main = putStrLn $ whichOne (undefined :: [Int])
लेकिन जीएचसी ओवरलैपिंग उदाहरणों के साथ ठीक नहीं है जब न तो स्पष्ट रूप से दूसरे की तुलना में बेहतर फिट है:
{-# LANGUAGE FlexibleInstances, OverlappingInstances #-}
class Foo a where
whichOne :: a -> String
instance Foo (f Int) where -- this is the line which changed
whichOne _ = "f Int"
instance Foo [a] where
whichOne _ = "[a]"
-- |
-- >>> main
-- Error: Overlapping instances for Foo [Int]
main :: IO ()
main = putStrLn $ whichOne (undefined :: [Int])
आपके प्रकार के हस्ताक्षर का उपयोग करता है SyntacticN (a -> (a -> b) -> b) fi
, और न SyntacticN f fi
ही SyntacticN (a -> f) (AST sym (Full ia) -> fi)
अन्य की तुलना में बेहतर फिट है। अगर मैं आपके प्रकार के उस हिस्से को SyntacticN a fi
या तो बदल देता हूँ याSyntacticN (a -> (a -> b) -> b) (AST sym (Full ia) -> fi)
, तो GHC अब ओवरलैप के बारे में शिकायत नहीं करता है।
यदि मैं आप थे, तो मैं उन दो संभावित उदाहरणों की परिभाषा को देखूंगा और यह निर्धारित करूंगा कि क्या उन दो कार्यान्वयनों में से एक आप चाहते हैं।
sugarSym Let
, जिसमें(SyntacticN f (ASTF sup a -> ASTF sup (a -> b) -> ASTF sup b), Let :<: sup) => f
अस्पष्ट प्रकार के चर शामिल नहीं हैं?