2015-03-12 9 views
6

मेरे पास कतारों के लिए एक कक्षा है जो उदाहरण को तत्वों पर मौजूद बाधाओं को परिभाषित करने की अनुमति देती है। उदाहरण के लिए, एक प्राथमिकता कतार orderable होने के लिए उसके तत्वों की आवश्यकता है:क्या मैं खाली बाधा प्रकार को पैरामीटर कर सकता हूं?

{-# LANGUAGE MultiParamTypeClasses, ConstraintKinds, FunctionalDependencies #-} 

class Queue q c | q -> c where 
    empty :: q a 
    qpop :: c a => q a -> Maybe (a, q a) 
    qpush :: c a => a -> q a -> q a 

data PriorityQueue a = ... 

instance Queue PriorityQueue Ord where 
    ... 

यह एक आकर्षण काम करता है: अंदर PriorityQueue के लिए उदाहरण घोषणा मैं कतार Ord जैसे (>) के सदस्यों का उपयोग कर के तत्वों पर काम कर सकते हैं। GHC से,

newtype LIFO a = LIFO [a] 

instance Queue LIFO() where 
    empty = LIFO [] 
    qpop (LIFO []) = Nothing 
    qpop (LIFO (x:xs)) = Just (x, LIFO xs) 
    qpush x (LIFO xs) = LIFO $ x:xs 

यह विफल रहता है निम्न त्रुटि संदेश के साथ:


मैं एक कतार जो उसके तत्वों पर कोई आवश्यकताओं स्थानों को परिभाषित करने की कोशिश कर अटक गया गया है

The second argument of `Queue' should have kind `* -> Constraint', 
    but `()' has kind `*' 
In the instance declaration for `Queue LIFO()' 

यह त्रुटि संदेश मुझे समझ में आता है। Eq एक प्रकार पैरामीटर स्वीकार करता है (हम आमतौर पर Eq a => ... लिखते हैं) जबकि () में कोई पैरामीटर नहीं है - यह एक सादा पुराना प्रकार का मेल नहीं है।


मैं एक प्रकार समारोह जो अपने दूसरे तर्क पर ध्यान नहीं देता है, जो मुझे instance Queue LIFO (Const()) लिखने के लिए अनुमति होगी लिख देने का प्रयास किया था:

{-# LANGUAGE TypeFamilies, KindSignatures, PolyKinds #-} 

type family Const a b :: k -> k2 -> k 
type instance Const a b = a 

मैं प्रकार परिवारों और तरह बहुरूपता काफी खूबसूरत के इस बातचीत मिल जाए, इसलिए मैं नहीं बल्कि निराश था जब यह काम नहीं किया (मैं वास्तव में सोचा था कि यह होगा!):

Expecting two more arguments to `a' 
The first argument of `Const' should have kind `*', 
    but `a' has kind `k0 -> k1 -> k0' 
In the type `a' 
In the type instance declaration for `Const' 

मुझे लगता है यह पिछले उदाहरण है कुछ की तरह बेवकूफ है एक वाक्यविन्यास गलती (मैं परिवारों को टाइप करने के लिए नया हूँ)। मैं Constraint कैसे लिख सकता हूं जो इसके तर्क पर कोई प्रतिबंध नहीं लगाता है?

+0

तो परिभाषित करने 'प्रकार परिवार कॉन्स्ट (क :: k1) (ख :: K2) प्रयास करें :: k1'' कॉन्स (() :: बाधा) 'जैसा कि आप चाहते हैं, हालांकि यह अभी भी अटक गया है। –

+0

@ जे। अब्राहमसन हाँ, ऐसा लगता है कि 'इंस्टेंस' घोषणा पर अटक गया: 'उदाहरण में अवैध प्रकार समानार्थी परिवार आवेदन'। 'कॉन्स्ट' पर मेरा मूल प्रयास क्यों विफल हुआ? –

+0

आप इसे 'TypeFamilies' के साथ करने में भी रुचि रखते हैं। http://www.skybluetrades.net/blog/posts/2015/03/08/constraint-kinds-associated-types.html – snak

उत्तर

7

यह काम करना चाहिए:

class NoConstraint a where 
instance NoConstraint a where 

instance Queue LIFO NoConstraint where 
    ... 

ऊपर की कोई समस्या है जो सभी प्रकार से संतुष्ट हो जाता है परिभाषित करता है। इस प्रकार, दायित्व c a जहां c = NoConstraint हमेशा छुट्टी दी जा सकती है। इसके अलावा, चूंकि उस वर्ग में कोई सदस्य नहीं हैं, इसलिए इसमें शून्य (या लगभग शून्य) रन-टाइम लागत होनी चाहिए।

"बाधा" () जिसे आप उपयोग करने का प्रयास कर रहे हैं उसे जीएचसी द्वारा निर्धारित खाली बाधा के रूप में नहीं देखा जाता है, लेकिन यूनिट के प्रकार () :: * के रूप में। यह Const() :: k2 -> * का कारण बनता है, जो कि प्रकार की त्रुटि को ट्रिगर करता है।

यदि आप कस्टम क्लास का उपयोग नहीं करना चाहते हैं, तो आप उदाहरण का प्रयास कर सकते हैं Const (Eq()) या Const (Num Int), जो सही प्रकार k2 -> Constraint है। मैं इसकी अनुशंसा नहीं करता, हालांकि, क्योंकि मुझे कस्टम क्लास का उपयोग करने से कम पठनीय लगता है।

(यह रूप में बेंजामिन हॉजसन नीचे बताते हैं एक टिप्पणी में, कुछ एक्सटेंशन को सक्षम करने की आवश्यकता है।)

+3

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

+0

समस्या जो मैं यहां देखता हूं वह यह है कि 'NoConstraint' बाधा कतार का उपयोग करके सबकुछ "संक्रमित" करेगी। 'कॉन्स्ट (NoConstraint())' का उपयोग करके इस के आसपास जाना संभव होगा? – dfeuer

+0

@dfeuer यदि आप सामान्य रूप से कतार का उपयोग कर रहे हैं, तो बाधा '(क्यूई क्यूसी, सीए) => क्यूए' जैसी दिखती है जो मुझे लगता है कि बहुत कठिन नहीं है –

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

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