2013-04-06 7 views
5

के साथ एक विषम डेटा संरचना पर मैपिंग मैं एक एचएलआईटी कार्यान्वयन पर काम कर रहा हूं और मैं इसके लिए map फ़ंक्शन को लागू करने की कोशिश कर रहा हूं। मैंने कई अलग-अलग दृष्टिकोणों की कोशिश की है, लेकिन प्रत्येक के साथ मैं उस फ़ंक्शन से संबंधित कंपाइलर त्रुटियों तक पहुंचता हूं।एक जेनेरिक फ़ंक्शन

इनपुट डेटा संरचना के सभी तत्वों पर लागू करने के लिए मैं एक सामान्य फ़ंक्शन Just का उपयोग कैसे करना चाहता हूं इसका एक उदाहरण निम्नलिखित है।

No instance for (Apply (a0 -> Maybe a0) Int (Maybe Int)) 
    arising from a use of `hMap' 
The type variable `a0' is ambiguous 

इस हल करने के लिए सभी के लिए एक रास्ता में वहाँ है और नहीं तो क्यों:

{-# LANGUAGE MultiParamTypeClasses #-} 
{-# LANGUAGE FlexibleInstances #-} 

-- | An input heterogenous data structure 
recursivePairs :: (Int, (Char, (Bool,()))) 
recursivePairs = (1, ('a', (True,()))) 

-- | This is how I want to use it 
recursivePairs' :: (Maybe Int, (Maybe Char, (Maybe Bool,()))) 
recursivePairs' = hMap Just recursivePairs 

class HMap f input output where 
    hMap :: f -> input -> output 

-- | A counterpart of a Nil pattern match for a list 
instance HMap f()() where 
    hMap _ _ =() 

-- | A counterpart of a Cons pattern match for a list 
instance 
    (HMap f iTail oTail, 
    Apply f iHead oHead) => 
    HMap f (iHead, iTail) (oHead, oTail) 
    where 
    hMap f (head, tail) = (apply f head, hMap f tail) 

class Apply f input output where 
    apply :: f -> input -> output 

instance Apply (input -> output) input output where 
    apply = id 
इस के साथ

मैं निम्नलिखित संकलक त्रुटि मिल रही है?

+0

मुझे लगता है कि समस्या यह है कि प्रकार प्रणाली एहसास नहीं है कि आप 'बाद एक आवेदन पर अलग ठोस प्रकार के साथ Just' instantiating रहे हैं, क्योंकि' hMap' की अपनी परिभाषा ही 'f' पुन: उपयोग रहता है। पहली बार जब आप इसे लागू करते हैं तो 'Int -> शायद Int' है, दूसरी बार जब आप इसे लागू करते हैं तो यह प्रकार' Char -> शायद Char' है। हालांकि, मुझे अभी भी यह सुनिश्चित नहीं है कि इसे कैसे ठीक किया जाए। –

+0

@ गैब्रियल गोंज़ालेज़ हां, यह बिल्कुल समस्या है। और यदि आप एक फंड जोड़ें '| इनपुट आउटपुट -> 'लागू' वर्ग में f', त्रुटि संदेश कहेंगे कि यह उदाहरणों की तलाश में है, जैसे '(बूल -> शायद बूल) चार (शायद चार)'। मैं ['cast'] (http: //hackage.haskell का उपयोग करने के बारे में सोच रहा था।संगठन/पैकेज/संग्रह/आधार/नवीनतम/डॉक्टर/एचटीएमएल/डेटा-टाइप करने योग्य.html # वी: कास्ट) एक प्रकार के स्तर पर 'एफ' के दो उपयोगों को डिस्कनेक्ट करने के लिए, लेकिन यह बहुत स्वाभाविक नहीं लग रहा था, और 'टाइप करने योग्य' के आधार पर या तो बहुत आकर्षक नहीं था। –

उत्तर

5

समस्या यह है कि आप विभिन्न तर्कों के साथ एक पॉलिमॉर्फिक फ़ंक्शन का उपयोग करने का प्रयास कर रहे हैं, लेकिन आपका Apply उदाहरण एक फ़ंक्शन (एक मोनो-टाइप) लेता है। है (RankNTypes की आवश्यकता होती है)

--A "universal" action that works on all types 
newtype Univ f = Univ (forall x. x -> f x) 
instance Apply (Univ f) x (f x) where 
    apply (Univ f) x = f x 

recursivePairs' :: (Maybe Int, (Maybe Char, (Maybe Bool,()))) 
recursivePairs' = hMap (Univ Just) recursivePairs 

एक ही बात करने के लिए एक अधिक सामान्य दृष्टिकोण या यदि आप कर रहे हैं: आप आसानी से इस के लिए कई तरीके ठीक कर सकते हैं अपने कोड ठीक

संपादित साथ

data JustIfy = JustIfy 
instance Apply JustIfy a (Maybe a) where 
    apply _ = Just 

recursivePairs' :: (Maybe Int, (Maybe Char, (Maybe Bool,()))) 
recursivePairs' = hMap JustIfy recursivePairs 

काम करता है जीएचसी के हालिया आईएसएच संस्करण का उपयोग करके और अधिक एक्सटेंशन चालू करने के लिए तैयार हैं

newtype Univ' c f = Univ' (forall x. c x => x -> f x) 
instance c x => Apply (Univ' c f) x (f x) where 
    apply (Univ' f) x = f x 

class All x 
instance All x 

recursivePairs' :: (Maybe Int, (Maybe Char, (Maybe Bool,()))) 
recursivePairs' = hMap (Univ' Just :: Univ' All Maybe) recursivePairs 

जो तब से अच्छा है, यह आपको उस कार्य में "शो" शामिल करने जैसी चीजों को करने देता है।

अधिक सामान्य समाधान के लिए, Oleg's Type level lambda caclulus देखें जो आपको मूल्य स्तर पर कोड लिखने की अनुमति देता है और फिर स्वत: जादुई रूप से उचित प्रकार के स्तर का प्रोग्राम करता है। दुर्भाग्यवश, ओलेग का समाधान इस बिंदु पर पुराना है, और एलसी के नाममात्र कार्यान्वयन का उपयोग करता है जिसे मैं विशेष रूप से पसंद नहीं करता हूं। मैं बेहतर तरीके से काम करने के बारे में सोच रहा हूं, लेकिन जब तक देनदार समानता परिवारों को टाइप करने के लिए आती है तब तक रोक लग सकती है।

मेरा विचार यह है कि इन दिनों एचएलआईटी को टीएडल्स के बजाय जीएडीटी और डेटाकिंड्स का उपयोग करके किया जाना चाहिए। टाइप करें परिवार कार्यात्मक निर्भरताओं के लिए बेहतर हैं, लेकिन वर्तमान में अधिक सीमित हैं क्योंकि उनमें कमजोर समानता की कमी है।

+0

धन्यवाद। आप कहते हैं कि इसे हल करने के कई तरीके हैं - क्या आप इस पर और विस्तार से बता सकते हैं? मैं एक इष्टतम समाधान की तलाश में हूं, इसलिए किसी भी तरह से प्रदान किए गए कोड से चिपकने की कोई आवश्यकता नहीं है, यह सिर्फ एक सार उदाहरण है। क्या प्रत्येक फंक्शन के लिए विशिष्ट उदाहरण घोषित किए बिना इसे हल करने का कोई तरीका है जिसे मैं 'hMap' के साथ उपयोग करना चाहता हूं? –

+0

@ निकितावोल्कोव मैंने अधिक सामान्य समाधान जोड़े हैं –

1

हालांकि निम्नलिखित वास्तव में सवाल (तो मैं इसे स्वीकार नहीं किया जाएगा) का जवाब नहीं है, यह अनुप्रयोगी functors के लिए कोई अतिरिक्त उदाहरणों की आवश्यकता के बिना संरचना मानचित्रण के विषय में समस्या को हल करता है:

{-# LANGUAGE MultiParamTypeClasses #-} 
{-# LANGUAGE FlexibleInstances #-} 

import Control.Applicative 

main = do 
    print $ (hPure recursivePairs :: (Maybe Int, (Maybe Char, (Maybe Bool,())))) 
    print $ (hPure recursivePairs :: ([Int], ([Char], ([Bool],())))) 

recursivePairs :: (Int, (Char, (Bool,()))) 
recursivePairs = (1, ('a', (True,()))) 

class HPure input output where 
    hPure :: input -> output 

instance HPure()() where 
    hPure _ =() 

instance 
    (Applicative f, 
    HPure iTail oTail) => 
    HPure (iHead, iTail) (f iHead, oTail) 
    where hPure (iHead, iTail) = (pure iHead, hPure iTail) 

आउटपुट :

(Just 1,(Just 'a',(Just True,()))) 
([1],("a",([True],()))) 
संबंधित मुद्दे